python/moz/l10n/message/to_json.py (74 lines of code) (raw):
# Copyright Mozilla Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
from typing import Any
from ..model import (
Expression,
Markup,
Message,
Pattern,
PatternMessage,
SelectMessage,
VariableRef,
)
def message_to_json(msg: Message) -> list[Any] | dict[str, Any]:
"""
Represent a Message as a JSON-serializable value.
The JSON Schema of the output is provided as [schema.json](./schema.json).
"""
json_declarations = {
name: _expression_to_json(expr) for name, expr in msg.declarations.items()
}
if isinstance(msg, PatternMessage):
if not json_declarations:
return _pattern_to_json(msg.pattern)
return {
"decl": json_declarations,
"msg": _pattern_to_json(msg.pattern),
}
else:
assert isinstance(msg, SelectMessage)
return {
"decl": json_declarations,
"sel": [sel.name for sel in msg.selectors],
"alt": [
{
"keys": [
key if isinstance(key, str) else {"*": key.value or ""}
for key in keys
],
"pat": _pattern_to_json(pattern),
}
for keys, pattern in msg.variants.items()
],
}
def _pattern_to_json(pattern: Pattern) -> list[str | dict[str, Any]]:
return [
part
if isinstance(part, str)
else _markup_to_json(part)
if isinstance(part, Markup)
else _expression_to_json(part)
for part in pattern
]
def _expression_to_json(expr: Expression) -> dict[str, Any]:
json: dict[str, Any] = {}
if isinstance(expr.arg, str):
json["_"] = expr.arg
elif isinstance(expr.arg, VariableRef):
json["$"] = expr.arg.name
if expr.function:
json["fn"] = expr.function
if expr.options:
json["opt"] = _options_to_json(expr.options)
if expr.attributes:
json["attr"] = expr.attributes
return json
def _markup_to_json(markup: Markup) -> dict[str, Any]:
json: dict[str, Any] = {
"elem" if markup.kind == "standalone" else markup.kind: markup.name
}
if markup.options:
json["opt"] = _options_to_json(markup.options)
if markup.attributes:
json["attr"] = markup.attributes
return json
def _options_to_json(options: dict[str, str | VariableRef]) -> dict[str, Any]:
return {
name: value if isinstance(value, str) else {"$": value.name}
for name, value in options.items()
}