multilingualprogramming 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- multilingualprogramming/__init__.py +74 -0
- multilingualprogramming/__main__.py +194 -0
- multilingualprogramming/codegen/__init__.py +12 -0
- multilingualprogramming/codegen/executor.py +215 -0
- multilingualprogramming/codegen/python_generator.py +592 -0
- multilingualprogramming/codegen/repl.py +489 -0
- multilingualprogramming/codegen/runtime_builtins.py +308 -0
- multilingualprogramming/core/__init__.py +12 -0
- multilingualprogramming/core/ir.py +29 -0
- multilingualprogramming/core/lowering.py +24 -0
- multilingualprogramming/datetime/__init__.py +11 -0
- multilingualprogramming/datetime/date_parser.py +190 -0
- multilingualprogramming/datetime/mp_date.py +210 -0
- multilingualprogramming/datetime/mp_datetime.py +153 -0
- multilingualprogramming/datetime/mp_time.py +147 -0
- multilingualprogramming/datetime/resource_loader.py +18 -0
- multilingualprogramming/exceptions.py +158 -0
- multilingualprogramming/imports.py +150 -0
- multilingualprogramming/keyword/__init__.py +13 -0
- multilingualprogramming/keyword/keyword_registry.py +249 -0
- multilingualprogramming/keyword/keyword_validator.py +59 -0
- multilingualprogramming/keyword/language_pack_validator.py +110 -0
- multilingualprogramming/lexer/__init__.py +11 -0
- multilingualprogramming/lexer/lexer.py +570 -0
- multilingualprogramming/lexer/source_reader.py +91 -0
- multilingualprogramming/lexer/token.py +54 -0
- multilingualprogramming/lexer/token_types.py +38 -0
- multilingualprogramming/numeral/__init__.py +11 -0
- multilingualprogramming/numeral/abstract_numeral.py +232 -0
- multilingualprogramming/numeral/complex_numeral.py +190 -0
- multilingualprogramming/numeral/fraction_numeral.py +165 -0
- multilingualprogramming/numeral/mp_numeral.py +243 -0
- multilingualprogramming/numeral/numeral_converter.py +151 -0
- multilingualprogramming/numeral/roman_numeral.py +301 -0
- multilingualprogramming/numeral/unicode_numeral.py +292 -0
- multilingualprogramming/parser/__init__.py +28 -0
- multilingualprogramming/parser/ast_nodes.py +459 -0
- multilingualprogramming/parser/ast_printer.py +677 -0
- multilingualprogramming/parser/error_messages.py +75 -0
- multilingualprogramming/parser/parser.py +1796 -0
- multilingualprogramming/parser/semantic_analyzer.py +689 -0
- multilingualprogramming/parser/surface_normalizer.py +282 -0
- multilingualprogramming/resources/datetime/eras.json +23 -0
- multilingualprogramming/resources/datetime/formats.json +32 -0
- multilingualprogramming/resources/datetime/months.json +150 -0
- multilingualprogramming/resources/datetime/weekdays.json +90 -0
- multilingualprogramming/resources/parser/error_messages.json +310 -0
- multilingualprogramming/resources/repl/commands.json +636 -0
- multilingualprogramming/resources/usm/builtins_aliases.json +731 -0
- multilingualprogramming/resources/usm/keywords.json +1063 -0
- multilingualprogramming/resources/usm/operators.json +532 -0
- multilingualprogramming/resources/usm/schema.json +34 -0
- multilingualprogramming/resources/usm/surface_patterns.json +1523 -0
- multilingualprogramming/unicode_string.py +140 -0
- multilingualprogramming/version.py +9 -0
- multilingualprogramming-0.2.0.dist-info/METADATA +350 -0
- multilingualprogramming-0.2.0.dist-info/RECORD +61 -0
- multilingualprogramming-0.2.0.dist-info/WHEEL +5 -0
- multilingualprogramming-0.2.0.dist-info/entry_points.txt +3 -0
- multilingualprogramming-0.2.0.dist-info/licenses/LICENSE +674 -0
- multilingualprogramming-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
#
|
|
2
|
+
# SPDX-FileCopyrightText: 2024 John Samuel <johnsamuelwrites@gmail.com>
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
"""Declarative surface-syntax normalization before canonical parsing."""
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from multilingualprogramming.keyword.keyword_registry import KeywordRegistry
|
|
13
|
+
from multilingualprogramming.lexer.token import Token
|
|
14
|
+
from multilingualprogramming.lexer.token_types import TokenType
|
|
15
|
+
|
|
16
|
+
_PAIRS = {"(": ")", "[": "]", "{": "}"}
|
|
17
|
+
_PATTERN_SPEC_KINDS = {"literal", "delimiter", "keyword", "identifier", "expr"}
|
|
18
|
+
_OUTPUT_SPEC_KINDS = {"keyword", "delimiter", "identifier_slot", "expr_slot"}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _ensure(condition, message):
|
|
22
|
+
if not condition:
|
|
23
|
+
raise ValueError(message)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _validate_keyword_spec(spec, context):
|
|
27
|
+
_ensure("concept" in spec, f"{context}: missing 'concept'")
|
|
28
|
+
_ensure(isinstance(spec["concept"], str), f"{context}: 'concept' must be a string")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _validate_delimiter_or_literal(spec, context):
|
|
32
|
+
_ensure("value" in spec, f"{context}: missing 'value'")
|
|
33
|
+
_ensure(isinstance(spec["value"], str), f"{context}: 'value' must be a string")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _validate_slot_spec(spec, context):
|
|
37
|
+
_ensure("slot" in spec, f"{context}: missing 'slot'")
|
|
38
|
+
_ensure(isinstance(spec["slot"], str), f"{context}: 'slot' must be a string")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _validate_pattern_spec(spec, context):
|
|
42
|
+
_ensure(isinstance(spec, dict), f"{context}: each entry must be an object")
|
|
43
|
+
kind = spec.get("kind")
|
|
44
|
+
_ensure(kind in _PATTERN_SPEC_KINDS, f"{context}: unsupported kind '{kind}'")
|
|
45
|
+
if kind == "keyword":
|
|
46
|
+
_validate_keyword_spec(spec, context)
|
|
47
|
+
elif kind in {"literal", "delimiter"}:
|
|
48
|
+
_validate_delimiter_or_literal(spec, context)
|
|
49
|
+
elif kind in {"identifier", "expr"}:
|
|
50
|
+
_validate_slot_spec(spec, context)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _validate_output_spec(spec, context):
|
|
54
|
+
_ensure(isinstance(spec, dict), f"{context}: each entry must be an object")
|
|
55
|
+
kind = spec.get("kind")
|
|
56
|
+
_ensure(kind in _OUTPUT_SPEC_KINDS, f"{context}: unsupported kind '{kind}'")
|
|
57
|
+
if kind == "keyword":
|
|
58
|
+
_validate_keyword_spec(spec, context)
|
|
59
|
+
elif kind == "delimiter":
|
|
60
|
+
_validate_delimiter_or_literal(spec, context)
|
|
61
|
+
elif kind in {"identifier_slot", "expr_slot"}:
|
|
62
|
+
_validate_slot_spec(spec, context)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def validate_surface_patterns_config(config):
|
|
66
|
+
"""Validate schema and internal consistency of surface pattern config."""
|
|
67
|
+
_ensure(isinstance(config, dict), "surface patterns config must be a JSON object")
|
|
68
|
+
|
|
69
|
+
templates = config.get("templates", {})
|
|
70
|
+
_ensure(isinstance(templates, dict), "'templates' must be an object when provided")
|
|
71
|
+
for name, specs in templates.items():
|
|
72
|
+
ctx = f"template '{name}'"
|
|
73
|
+
_ensure(isinstance(name, str), "template names must be strings")
|
|
74
|
+
_ensure(isinstance(specs, list) and specs, f"{ctx}: must be a non-empty list")
|
|
75
|
+
for idx, spec in enumerate(specs):
|
|
76
|
+
_validate_output_spec(spec, f"{ctx}[{idx}]")
|
|
77
|
+
|
|
78
|
+
patterns = config.get("patterns")
|
|
79
|
+
_ensure(isinstance(patterns, list) and patterns, "'patterns' must be a non-empty list")
|
|
80
|
+
|
|
81
|
+
registry = KeywordRegistry()
|
|
82
|
+
supported_languages = set(registry.get_supported_languages())
|
|
83
|
+
|
|
84
|
+
for ridx, rule in enumerate(patterns):
|
|
85
|
+
ctx = f"pattern[{ridx}]"
|
|
86
|
+
_ensure(isinstance(rule, dict), f"{ctx}: must be an object")
|
|
87
|
+
_ensure(isinstance(rule.get("name"), str), f"{ctx}: missing/invalid 'name'")
|
|
88
|
+
_ensure(isinstance(rule.get("language"), str), f"{ctx}: missing/invalid 'language'")
|
|
89
|
+
_ensure(rule["language"] in supported_languages,
|
|
90
|
+
f"{ctx}: unsupported language '{rule['language']}'")
|
|
91
|
+
|
|
92
|
+
pattern_specs = rule.get("pattern")
|
|
93
|
+
_ensure(isinstance(pattern_specs, list) and pattern_specs,
|
|
94
|
+
f"{ctx}: 'pattern' must be a non-empty list")
|
|
95
|
+
captured_slots = set()
|
|
96
|
+
for sidx, spec in enumerate(pattern_specs):
|
|
97
|
+
_validate_pattern_spec(spec, f"{ctx}.pattern[{sidx}]")
|
|
98
|
+
if spec["kind"] in {"identifier", "expr"}:
|
|
99
|
+
captured_slots.add(spec["slot"])
|
|
100
|
+
|
|
101
|
+
has_norm = "normalize_to" in rule
|
|
102
|
+
has_template = "normalize_template" in rule
|
|
103
|
+
_ensure(has_norm ^ has_template,
|
|
104
|
+
f"{ctx}: provide exactly one of 'normalize_to' or 'normalize_template'")
|
|
105
|
+
|
|
106
|
+
output_specs = None
|
|
107
|
+
if has_norm:
|
|
108
|
+
output_specs = rule.get("normalize_to")
|
|
109
|
+
_ensure(isinstance(output_specs, list) and output_specs,
|
|
110
|
+
f"{ctx}: 'normalize_to' must be a non-empty list")
|
|
111
|
+
else:
|
|
112
|
+
tname = rule.get("normalize_template")
|
|
113
|
+
_ensure(isinstance(tname, str), f"{ctx}: 'normalize_template' must be a string")
|
|
114
|
+
_ensure(tname in templates, f"{ctx}: unknown template '{tname}'")
|
|
115
|
+
output_specs = templates[tname]
|
|
116
|
+
|
|
117
|
+
for oidx, spec in enumerate(output_specs):
|
|
118
|
+
_validate_output_spec(spec, f"{ctx}.normalize[{oidx}]")
|
|
119
|
+
if spec["kind"] in {"identifier_slot", "expr_slot"}:
|
|
120
|
+
_ensure(spec["slot"] in captured_slots,
|
|
121
|
+
f"{ctx}: output references unknown slot '{spec['slot']}'")
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class SurfaceNormalizer:
|
|
125
|
+
"""Normalize language-specific surface patterns to canonical token order."""
|
|
126
|
+
|
|
127
|
+
_patterns = None
|
|
128
|
+
_templates = None
|
|
129
|
+
|
|
130
|
+
@classmethod
|
|
131
|
+
def _load_patterns(cls):
|
|
132
|
+
if cls._patterns is not None:
|
|
133
|
+
return cls._patterns
|
|
134
|
+
|
|
135
|
+
path = (
|
|
136
|
+
Path(__file__).resolve().parent.parent
|
|
137
|
+
/ "resources" / "usm" / "surface_patterns.json"
|
|
138
|
+
)
|
|
139
|
+
with open(path, "r", encoding="utf-8-sig") as handle:
|
|
140
|
+
data = json.load(handle)
|
|
141
|
+
validate_surface_patterns_config(data)
|
|
142
|
+
cls._templates = data.get("templates", {})
|
|
143
|
+
cls._patterns = data.get("patterns", [])
|
|
144
|
+
return cls._patterns
|
|
145
|
+
|
|
146
|
+
@staticmethod
|
|
147
|
+
def _is_boundary(token):
|
|
148
|
+
return token.type in (TokenType.NEWLINE, TokenType.EOF)
|
|
149
|
+
|
|
150
|
+
@staticmethod
|
|
151
|
+
def _is_statement_start(tokens, index):
|
|
152
|
+
if index == 0:
|
|
153
|
+
return True
|
|
154
|
+
prev = tokens[index - 1]
|
|
155
|
+
return prev.type in (TokenType.NEWLINE, TokenType.INDENT, TokenType.DEDENT)
|
|
156
|
+
|
|
157
|
+
@staticmethod
|
|
158
|
+
def _match_single(token, spec):
|
|
159
|
+
kind = spec.get("kind")
|
|
160
|
+
if kind == "literal":
|
|
161
|
+
return token.value == spec.get("value")
|
|
162
|
+
if kind == "delimiter":
|
|
163
|
+
return token.type == TokenType.DELIMITER and token.value == spec.get("value")
|
|
164
|
+
if kind == "keyword":
|
|
165
|
+
return token.type == TokenType.KEYWORD and token.concept == spec.get("concept")
|
|
166
|
+
if kind == "identifier":
|
|
167
|
+
return token.type == TokenType.IDENTIFIER
|
|
168
|
+
return False
|
|
169
|
+
|
|
170
|
+
def _find_expr_end(self, tokens, start_idx, next_spec):
|
|
171
|
+
idx = start_idx
|
|
172
|
+
depth = 0
|
|
173
|
+
|
|
174
|
+
while idx < len(tokens):
|
|
175
|
+
tok = tokens[idx]
|
|
176
|
+
if depth == 0 and self._is_boundary(tok):
|
|
177
|
+
break
|
|
178
|
+
|
|
179
|
+
if tok.type == TokenType.DELIMITER:
|
|
180
|
+
if tok.value in _PAIRS:
|
|
181
|
+
depth += 1
|
|
182
|
+
elif tok.value in _PAIRS.values():
|
|
183
|
+
depth = max(0, depth - 1)
|
|
184
|
+
|
|
185
|
+
if depth == 0 and next_spec is not None:
|
|
186
|
+
if self._match_single(tok, next_spec):
|
|
187
|
+
break
|
|
188
|
+
idx += 1
|
|
189
|
+
|
|
190
|
+
return idx
|
|
191
|
+
|
|
192
|
+
def _render_token(self, spec, slots, language, anchor):
|
|
193
|
+
kind = spec.get("kind")
|
|
194
|
+
if kind == "keyword":
|
|
195
|
+
concept = spec.get("concept")
|
|
196
|
+
value = KeywordRegistry().get_keyword(concept, language)
|
|
197
|
+
return Token(
|
|
198
|
+
TokenType.KEYWORD, value, anchor.line, anchor.column,
|
|
199
|
+
concept=concept, language=language
|
|
200
|
+
)
|
|
201
|
+
if kind == "delimiter":
|
|
202
|
+
return Token(TokenType.DELIMITER, spec.get("value"), anchor.line, anchor.column)
|
|
203
|
+
if kind == "identifier_slot":
|
|
204
|
+
return slots[spec.get("slot")]
|
|
205
|
+
return None
|
|
206
|
+
|
|
207
|
+
def _render_output(self, rule, slots, language, anchor):
|
|
208
|
+
normalize_to = rule.get("normalize_to")
|
|
209
|
+
template_name = rule.get("normalize_template")
|
|
210
|
+
if normalize_to is None and template_name:
|
|
211
|
+
normalize_to = (self._templates or {}).get(template_name, [])
|
|
212
|
+
|
|
213
|
+
out = []
|
|
214
|
+
for spec in normalize_to or []:
|
|
215
|
+
kind = spec.get("kind")
|
|
216
|
+
if kind == "expr_slot":
|
|
217
|
+
out.extend(slots[spec.get("slot")])
|
|
218
|
+
continue
|
|
219
|
+
tok = self._render_token(spec, slots, language, anchor)
|
|
220
|
+
if tok is not None:
|
|
221
|
+
out.append(tok)
|
|
222
|
+
return out
|
|
223
|
+
|
|
224
|
+
def _match_rule(self, tokens, start_idx, rule, language):
|
|
225
|
+
if language != rule.get("language"):
|
|
226
|
+
return None
|
|
227
|
+
if not self._is_statement_start(tokens, start_idx):
|
|
228
|
+
return None
|
|
229
|
+
|
|
230
|
+
idx = start_idx
|
|
231
|
+
slots = {}
|
|
232
|
+
specs = rule.get("pattern", [])
|
|
233
|
+
for pos, spec in enumerate(specs):
|
|
234
|
+
kind = spec.get("kind")
|
|
235
|
+
if kind == "expr":
|
|
236
|
+
next_spec = specs[pos + 1] if pos + 1 < len(specs) else None
|
|
237
|
+
expr_end = self._find_expr_end(tokens, idx, next_spec)
|
|
238
|
+
if expr_end <= idx:
|
|
239
|
+
return None
|
|
240
|
+
slots[spec.get("slot")] = tokens[idx:expr_end]
|
|
241
|
+
idx = expr_end
|
|
242
|
+
if idx >= len(tokens):
|
|
243
|
+
return None
|
|
244
|
+
continue
|
|
245
|
+
|
|
246
|
+
if idx >= len(tokens) or not self._match_single(tokens[idx], spec):
|
|
247
|
+
return None
|
|
248
|
+
if kind == "identifier":
|
|
249
|
+
slots[spec.get("slot")] = tokens[idx]
|
|
250
|
+
idx += 1
|
|
251
|
+
|
|
252
|
+
out = self._render_output(rule, slots, language, tokens[start_idx])
|
|
253
|
+
return idx, out
|
|
254
|
+
|
|
255
|
+
def normalize(self, tokens, language):
|
|
256
|
+
"""Return a new token list with declarative surface patterns normalized."""
|
|
257
|
+
patterns = self._load_patterns()
|
|
258
|
+
normalized = []
|
|
259
|
+
i = 0
|
|
260
|
+
while i < len(tokens):
|
|
261
|
+
replaced = False
|
|
262
|
+
for rule in patterns:
|
|
263
|
+
matched = self._match_rule(tokens, i, rule, language)
|
|
264
|
+
if matched is None:
|
|
265
|
+
continue
|
|
266
|
+
end_idx, replacement = matched
|
|
267
|
+
normalized.extend(replacement)
|
|
268
|
+
i = end_idx
|
|
269
|
+
replaced = True
|
|
270
|
+
break
|
|
271
|
+
if replaced:
|
|
272
|
+
continue
|
|
273
|
+
normalized.append(tokens[i])
|
|
274
|
+
i += 1
|
|
275
|
+
return normalized
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def normalize_surface_tokens(tokens, language):
|
|
279
|
+
"""Convenience wrapper used by parser entry points."""
|
|
280
|
+
if not language:
|
|
281
|
+
return tokens
|
|
282
|
+
return SurfaceNormalizer().normalize(tokens, language)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0",
|
|
3
|
+
"description": "Calendar era names for display purposes",
|
|
4
|
+
"eras": {
|
|
5
|
+
"GREGORIAN": {
|
|
6
|
+
"en": {"ce": "CE", "bce": "BCE"},
|
|
7
|
+
"fr": {"ce": "apr. J.-C.", "bce": "av. J.-C."},
|
|
8
|
+
"es": {"ce": "d.C.", "bce": "a.C."},
|
|
9
|
+
"de": {"ce": "n. Chr.", "bce": "v. Chr."},
|
|
10
|
+
"hi": {"ce": "ईस्वी", "bce": "ईसा पूर्व"},
|
|
11
|
+
"ar": {"ce": "م", "bce": "ق.م"},
|
|
12
|
+
"bn": {"ce": "খ্রিস্টাব্দ", "bce": "খ্রিস্টপূর্ব"},
|
|
13
|
+
"ta": {"ce": "கி.பி.", "bce": "கி.மு."},
|
|
14
|
+
"zh": {"ce": "公元", "bce": "公元前"},
|
|
15
|
+
"ja": {"ce": "西暦", "bce": "紀元前"}
|
|
16
|
+
},
|
|
17
|
+
"JAPANESE": {
|
|
18
|
+
"reiwa": {"ja": "令和", "en": "Reiwa", "start_year": 2019},
|
|
19
|
+
"heisei": {"ja": "平成", "en": "Heisei", "start_year": 1989},
|
|
20
|
+
"showa": {"ja": "昭和", "en": "Showa", "start_year": 1926}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0",
|
|
3
|
+
"description": "Date and time format patterns per language/locale",
|
|
4
|
+
"date_formats": {
|
|
5
|
+
"en": {"full": "DD-MONTH-YYYY", "short": "MM/DD/YYYY", "iso": "YYYY-MM-DD"},
|
|
6
|
+
"fr": {"full": "DD-MONTH-YYYY", "short": "DD/MM/YYYY", "iso": "YYYY-MM-DD"},
|
|
7
|
+
"es": {"full": "DD-MONTH-YYYY", "short": "DD/MM/YYYY", "iso": "YYYY-MM-DD"},
|
|
8
|
+
"de": {"full": "DD-MONTH-YYYY", "short": "DD.MM.YYYY", "iso": "YYYY-MM-DD"},
|
|
9
|
+
"hi": {"full": "DD-MONTH-YYYY", "short": "DD/MM/YYYY", "iso": "YYYY-MM-DD"},
|
|
10
|
+
"ar": {"full": "DD-MONTH-YYYY", "short": "DD/MM/YYYY", "iso": "YYYY-MM-DD"},
|
|
11
|
+
"bn": {"full": "DD-MONTH-YYYY", "short": "DD/MM/YYYY", "iso": "YYYY-MM-DD"},
|
|
12
|
+
"ta": {"full": "DD-MONTH-YYYY", "short": "DD/MM/YYYY", "iso": "YYYY-MM-DD"},
|
|
13
|
+
"zh": {"full": "YYYY年MM月DD日", "short": "YYYY/MM/DD", "iso": "YYYY-MM-DD"},
|
|
14
|
+
"ja": {"full": "YYYY年MM月DD日", "short": "YYYY/MM/DD", "iso": "YYYY-MM-DD"}
|
|
15
|
+
},
|
|
16
|
+
"time_formats": {
|
|
17
|
+
"en": {"24h": "HH:MM:SS", "12h": "hh:MM:SS AM/PM"},
|
|
18
|
+
"fr": {"24h": "HH:MM:SS", "12h": "hh:MM:SS"},
|
|
19
|
+
"es": {"24h": "HH:MM:SS", "12h": "hh:MM:SS a.m./p.m."},
|
|
20
|
+
"de": {"24h": "HH:MM:SS", "12h": "hh:MM:SS"},
|
|
21
|
+
"hi": {"24h": "HH:MM:SS", "12h": "hh:MM:SS पूर्वाह्न/अपराह्न"},
|
|
22
|
+
"ar": {"24h": "HH:MM:SS", "12h": "hh:MM:SS ص/م"},
|
|
23
|
+
"bn": {"24h": "HH:MM:SS", "12h": "hh:MM:SS পূর্বাহ্ন/অপরাহ্ন"},
|
|
24
|
+
"ta": {"24h": "HH:MM:SS", "12h": "hh:MM:SS முற்பகல்/பிற்பகல்"},
|
|
25
|
+
"zh": {"24h": "HH:MM:SS", "12h": "上午/下午 hh:MM:SS"},
|
|
26
|
+
"ja": {"24h": "HH:MM:SS", "12h": "午前/午後 hh:MM:SS"}
|
|
27
|
+
},
|
|
28
|
+
"separator": {
|
|
29
|
+
"en": "-", "fr": "-", "es": "-", "de": ".", "hi": "-",
|
|
30
|
+
"ar": "-", "bn": "-", "ta": "-", "zh": "", "ja": ""
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0",
|
|
3
|
+
"description": "Month names in multiple languages (Gregorian calendar)",
|
|
4
|
+
"months": {
|
|
5
|
+
"JANUARY": {
|
|
6
|
+
"en": {"full": "January", "abbr": "Jan"},
|
|
7
|
+
"fr": {"full": "Janvier", "abbr": "Jan"},
|
|
8
|
+
"es": {"full": "Enero", "abbr": "Ene"},
|
|
9
|
+
"de": {"full": "Januar", "abbr": "Jan"},
|
|
10
|
+
"hi": {"full": "जनवरी", "abbr": "जन"},
|
|
11
|
+
"ar": {"full": "يناير", "abbr": "ينا"},
|
|
12
|
+
"bn": {"full": "জানুয়ারি", "abbr": "জানু"},
|
|
13
|
+
"ta": {"full": "ஜனவரி", "abbr": "ஜன"},
|
|
14
|
+
"zh": {"full": "一月", "abbr": "1月"},
|
|
15
|
+
"ja": {"full": "一月", "abbr": "1月"}
|
|
16
|
+
},
|
|
17
|
+
"FEBRUARY": {
|
|
18
|
+
"en": {"full": "February", "abbr": "Feb"},
|
|
19
|
+
"fr": {"full": "Février", "abbr": "Fév"},
|
|
20
|
+
"es": {"full": "Febrero", "abbr": "Feb"},
|
|
21
|
+
"de": {"full": "Februar", "abbr": "Feb"},
|
|
22
|
+
"hi": {"full": "फ़रवरी", "abbr": "फ़र"},
|
|
23
|
+
"ar": {"full": "فبراير", "abbr": "فبر"},
|
|
24
|
+
"bn": {"full": "ফেব্রুয়ারি", "abbr": "ফেব"},
|
|
25
|
+
"ta": {"full": "பிப்ரவரி", "abbr": "பிப்"},
|
|
26
|
+
"zh": {"full": "二月", "abbr": "2月"},
|
|
27
|
+
"ja": {"full": "二月", "abbr": "2月"}
|
|
28
|
+
},
|
|
29
|
+
"MARCH": {
|
|
30
|
+
"en": {"full": "March", "abbr": "Mar"},
|
|
31
|
+
"fr": {"full": "Mars", "abbr": "Mar"},
|
|
32
|
+
"es": {"full": "Marzo", "abbr": "Mar"},
|
|
33
|
+
"de": {"full": "März", "abbr": "Mär"},
|
|
34
|
+
"hi": {"full": "मार्च", "abbr": "मार"},
|
|
35
|
+
"ar": {"full": "مارس", "abbr": "مار"},
|
|
36
|
+
"bn": {"full": "মার্চ", "abbr": "মার"},
|
|
37
|
+
"ta": {"full": "மார்ச்", "abbr": "மார்"},
|
|
38
|
+
"zh": {"full": "三月", "abbr": "3月"},
|
|
39
|
+
"ja": {"full": "三月", "abbr": "3月"}
|
|
40
|
+
},
|
|
41
|
+
"APRIL": {
|
|
42
|
+
"en": {"full": "April", "abbr": "Apr"},
|
|
43
|
+
"fr": {"full": "Avril", "abbr": "Avr"},
|
|
44
|
+
"es": {"full": "Abril", "abbr": "Abr"},
|
|
45
|
+
"de": {"full": "April", "abbr": "Apr"},
|
|
46
|
+
"hi": {"full": "अप्रैल", "abbr": "अप्रै"},
|
|
47
|
+
"ar": {"full": "أبريل", "abbr": "أبر"},
|
|
48
|
+
"bn": {"full": "এপ্রিল", "abbr": "এপ্রি"},
|
|
49
|
+
"ta": {"full": "ஏப்ரல்", "abbr": "ஏப்"},
|
|
50
|
+
"zh": {"full": "四月", "abbr": "4月"},
|
|
51
|
+
"ja": {"full": "四月", "abbr": "4月"}
|
|
52
|
+
},
|
|
53
|
+
"MAY": {
|
|
54
|
+
"en": {"full": "May", "abbr": "May"},
|
|
55
|
+
"fr": {"full": "Mai", "abbr": "Mai"},
|
|
56
|
+
"es": {"full": "Mayo", "abbr": "May"},
|
|
57
|
+
"de": {"full": "Mai", "abbr": "Mai"},
|
|
58
|
+
"hi": {"full": "मई", "abbr": "मई"},
|
|
59
|
+
"ar": {"full": "مايو", "abbr": "ماي"},
|
|
60
|
+
"bn": {"full": "মে", "abbr": "মে"},
|
|
61
|
+
"ta": {"full": "மே", "abbr": "மே"},
|
|
62
|
+
"zh": {"full": "五月", "abbr": "5月"},
|
|
63
|
+
"ja": {"full": "五月", "abbr": "5月"}
|
|
64
|
+
},
|
|
65
|
+
"JUNE": {
|
|
66
|
+
"en": {"full": "June", "abbr": "Jun"},
|
|
67
|
+
"fr": {"full": "Juin", "abbr": "Jun"},
|
|
68
|
+
"es": {"full": "Junio", "abbr": "Jun"},
|
|
69
|
+
"de": {"full": "Juni", "abbr": "Jun"},
|
|
70
|
+
"hi": {"full": "जून", "abbr": "जून"},
|
|
71
|
+
"ar": {"full": "يونيو", "abbr": "يون"},
|
|
72
|
+
"bn": {"full": "জুন", "abbr": "জুন"},
|
|
73
|
+
"ta": {"full": "ஜூன்", "abbr": "ஜூன்"},
|
|
74
|
+
"zh": {"full": "六月", "abbr": "6月"},
|
|
75
|
+
"ja": {"full": "六月", "abbr": "6月"}
|
|
76
|
+
},
|
|
77
|
+
"JULY": {
|
|
78
|
+
"en": {"full": "July", "abbr": "Jul"},
|
|
79
|
+
"fr": {"full": "Juillet", "abbr": "Jul"},
|
|
80
|
+
"es": {"full": "Julio", "abbr": "Jul"},
|
|
81
|
+
"de": {"full": "Juli", "abbr": "Jul"},
|
|
82
|
+
"hi": {"full": "जुलाई", "abbr": "जुल"},
|
|
83
|
+
"ar": {"full": "يوليو", "abbr": "يول"},
|
|
84
|
+
"bn": {"full": "জুলাই", "abbr": "জুল"},
|
|
85
|
+
"ta": {"full": "ஜூலை", "abbr": "ஜூலை"},
|
|
86
|
+
"zh": {"full": "七月", "abbr": "7月"},
|
|
87
|
+
"ja": {"full": "七月", "abbr": "7月"}
|
|
88
|
+
},
|
|
89
|
+
"AUGUST": {
|
|
90
|
+
"en": {"full": "August", "abbr": "Aug"},
|
|
91
|
+
"fr": {"full": "Août", "abbr": "Aoû"},
|
|
92
|
+
"es": {"full": "Agosto", "abbr": "Ago"},
|
|
93
|
+
"de": {"full": "August", "abbr": "Aug"},
|
|
94
|
+
"hi": {"full": "अगस्त", "abbr": "अग"},
|
|
95
|
+
"ar": {"full": "أغسطس", "abbr": "أغس"},
|
|
96
|
+
"bn": {"full": "আগস্ট", "abbr": "আগ"},
|
|
97
|
+
"ta": {"full": "ஆகஸ்ட்", "abbr": "ஆக"},
|
|
98
|
+
"zh": {"full": "八月", "abbr": "8月"},
|
|
99
|
+
"ja": {"full": "八月", "abbr": "8月"}
|
|
100
|
+
},
|
|
101
|
+
"SEPTEMBER": {
|
|
102
|
+
"en": {"full": "September", "abbr": "Sep"},
|
|
103
|
+
"fr": {"full": "Septembre", "abbr": "Sep"},
|
|
104
|
+
"es": {"full": "Septiembre", "abbr": "Sep"},
|
|
105
|
+
"de": {"full": "September", "abbr": "Sep"},
|
|
106
|
+
"hi": {"full": "सितम्बर", "abbr": "सित"},
|
|
107
|
+
"ar": {"full": "سبتمبر", "abbr": "سبت"},
|
|
108
|
+
"bn": {"full": "সেপ্টেম্বর", "abbr": "সেপ"},
|
|
109
|
+
"ta": {"full": "செப்டம்பர்", "abbr": "செப்"},
|
|
110
|
+
"zh": {"full": "九月", "abbr": "9月"},
|
|
111
|
+
"ja": {"full": "九月", "abbr": "9月"}
|
|
112
|
+
},
|
|
113
|
+
"OCTOBER": {
|
|
114
|
+
"en": {"full": "October", "abbr": "Oct"},
|
|
115
|
+
"fr": {"full": "Octobre", "abbr": "Oct"},
|
|
116
|
+
"es": {"full": "Octubre", "abbr": "Oct"},
|
|
117
|
+
"de": {"full": "Oktober", "abbr": "Okt"},
|
|
118
|
+
"hi": {"full": "अक्टूबर", "abbr": "अक्टू"},
|
|
119
|
+
"ar": {"full": "أكتوبر", "abbr": "أكت"},
|
|
120
|
+
"bn": {"full": "অক্টোবর", "abbr": "অক্টো"},
|
|
121
|
+
"ta": {"full": "அக்டோபர்", "abbr": "அக்"},
|
|
122
|
+
"zh": {"full": "十月", "abbr": "10月"},
|
|
123
|
+
"ja": {"full": "十月", "abbr": "10月"}
|
|
124
|
+
},
|
|
125
|
+
"NOVEMBER": {
|
|
126
|
+
"en": {"full": "November", "abbr": "Nov"},
|
|
127
|
+
"fr": {"full": "Novembre", "abbr": "Nov"},
|
|
128
|
+
"es": {"full": "Noviembre", "abbr": "Nov"},
|
|
129
|
+
"de": {"full": "November", "abbr": "Nov"},
|
|
130
|
+
"hi": {"full": "नवम्बर", "abbr": "नव"},
|
|
131
|
+
"ar": {"full": "نوفمبر", "abbr": "نوف"},
|
|
132
|
+
"bn": {"full": "নভেম্বর", "abbr": "নভ"},
|
|
133
|
+
"ta": {"full": "நவம்பர்", "abbr": "நவ"},
|
|
134
|
+
"zh": {"full": "十一月", "abbr": "11月"},
|
|
135
|
+
"ja": {"full": "十一月", "abbr": "11月"}
|
|
136
|
+
},
|
|
137
|
+
"DECEMBER": {
|
|
138
|
+
"en": {"full": "December", "abbr": "Dec"},
|
|
139
|
+
"fr": {"full": "Décembre", "abbr": "Déc"},
|
|
140
|
+
"es": {"full": "Diciembre", "abbr": "Dic"},
|
|
141
|
+
"de": {"full": "Dezember", "abbr": "Dez"},
|
|
142
|
+
"hi": {"full": "दिसम्बर", "abbr": "दिस"},
|
|
143
|
+
"ar": {"full": "ديسمبر", "abbr": "ديس"},
|
|
144
|
+
"bn": {"full": "ডিসেম্বর", "abbr": "ডিস"},
|
|
145
|
+
"ta": {"full": "டிசம்பர்", "abbr": "டிச"},
|
|
146
|
+
"zh": {"full": "十二月", "abbr": "12月"},
|
|
147
|
+
"ja": {"full": "十二月", "abbr": "12月"}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0",
|
|
3
|
+
"description": "Weekday names in multiple languages",
|
|
4
|
+
"weekdays": {
|
|
5
|
+
"MONDAY": {
|
|
6
|
+
"en": {"full": "Monday", "abbr": "Mon"},
|
|
7
|
+
"fr": {"full": "Lundi", "abbr": "Lun"},
|
|
8
|
+
"es": {"full": "Lunes", "abbr": "Lun"},
|
|
9
|
+
"de": {"full": "Montag", "abbr": "Mo"},
|
|
10
|
+
"hi": {"full": "सोमवार", "abbr": "सोम"},
|
|
11
|
+
"ar": {"full": "الاثنين", "abbr": "اثن"},
|
|
12
|
+
"bn": {"full": "সোমবার", "abbr": "সোম"},
|
|
13
|
+
"ta": {"full": "திங்கள்", "abbr": "திங்"},
|
|
14
|
+
"zh": {"full": "星期一", "abbr": "周一"},
|
|
15
|
+
"ja": {"full": "月曜日", "abbr": "月"}
|
|
16
|
+
},
|
|
17
|
+
"TUESDAY": {
|
|
18
|
+
"en": {"full": "Tuesday", "abbr": "Tue"},
|
|
19
|
+
"fr": {"full": "Mardi", "abbr": "Mar"},
|
|
20
|
+
"es": {"full": "Martes", "abbr": "Mar"},
|
|
21
|
+
"de": {"full": "Dienstag", "abbr": "Di"},
|
|
22
|
+
"hi": {"full": "मंगलवार", "abbr": "मंगल"},
|
|
23
|
+
"ar": {"full": "الثلاثاء", "abbr": "ثلا"},
|
|
24
|
+
"bn": {"full": "মঙ্গলবার", "abbr": "মঙ্গল"},
|
|
25
|
+
"ta": {"full": "செவ்வாய்", "abbr": "செவ்"},
|
|
26
|
+
"zh": {"full": "星期二", "abbr": "周二"},
|
|
27
|
+
"ja": {"full": "火曜日", "abbr": "火"}
|
|
28
|
+
},
|
|
29
|
+
"WEDNESDAY": {
|
|
30
|
+
"en": {"full": "Wednesday", "abbr": "Wed"},
|
|
31
|
+
"fr": {"full": "Mercredi", "abbr": "Mer"},
|
|
32
|
+
"es": {"full": "Miércoles", "abbr": "Mié"},
|
|
33
|
+
"de": {"full": "Mittwoch", "abbr": "Mi"},
|
|
34
|
+
"hi": {"full": "बुधवार", "abbr": "बुध"},
|
|
35
|
+
"ar": {"full": "الأربعاء", "abbr": "أرب"},
|
|
36
|
+
"bn": {"full": "বুধবার", "abbr": "বুধ"},
|
|
37
|
+
"ta": {"full": "புதன்", "abbr": "புத"},
|
|
38
|
+
"zh": {"full": "星期三", "abbr": "周三"},
|
|
39
|
+
"ja": {"full": "水曜日", "abbr": "水"}
|
|
40
|
+
},
|
|
41
|
+
"THURSDAY": {
|
|
42
|
+
"en": {"full": "Thursday", "abbr": "Thu"},
|
|
43
|
+
"fr": {"full": "Jeudi", "abbr": "Jeu"},
|
|
44
|
+
"es": {"full": "Jueves", "abbr": "Jue"},
|
|
45
|
+
"de": {"full": "Donnerstag", "abbr": "Do"},
|
|
46
|
+
"hi": {"full": "गुरुवार", "abbr": "गुरु"},
|
|
47
|
+
"ar": {"full": "الخميس", "abbr": "خمي"},
|
|
48
|
+
"bn": {"full": "বৃহস্পতিবার", "abbr": "বৃহ"},
|
|
49
|
+
"ta": {"full": "வியாழன்", "abbr": "வியா"},
|
|
50
|
+
"zh": {"full": "星期四", "abbr": "周四"},
|
|
51
|
+
"ja": {"full": "木曜日", "abbr": "木"}
|
|
52
|
+
},
|
|
53
|
+
"FRIDAY": {
|
|
54
|
+
"en": {"full": "Friday", "abbr": "Fri"},
|
|
55
|
+
"fr": {"full": "Vendredi", "abbr": "Ven"},
|
|
56
|
+
"es": {"full": "Viernes", "abbr": "Vie"},
|
|
57
|
+
"de": {"full": "Freitag", "abbr": "Fr"},
|
|
58
|
+
"hi": {"full": "शुक्रवार", "abbr": "शुक्र"},
|
|
59
|
+
"ar": {"full": "الجمعة", "abbr": "جمع"},
|
|
60
|
+
"bn": {"full": "শুক্রবার", "abbr": "শুক্র"},
|
|
61
|
+
"ta": {"full": "வெள்ளி", "abbr": "வெள்"},
|
|
62
|
+
"zh": {"full": "星期五", "abbr": "周五"},
|
|
63
|
+
"ja": {"full": "金曜日", "abbr": "金"}
|
|
64
|
+
},
|
|
65
|
+
"SATURDAY": {
|
|
66
|
+
"en": {"full": "Saturday", "abbr": "Sat"},
|
|
67
|
+
"fr": {"full": "Samedi", "abbr": "Sam"},
|
|
68
|
+
"es": {"full": "Sábado", "abbr": "Sáb"},
|
|
69
|
+
"de": {"full": "Samstag", "abbr": "Sa"},
|
|
70
|
+
"hi": {"full": "शनिवार", "abbr": "शनि"},
|
|
71
|
+
"ar": {"full": "السبت", "abbr": "سبت"},
|
|
72
|
+
"bn": {"full": "শনিবার", "abbr": "শনি"},
|
|
73
|
+
"ta": {"full": "சனி", "abbr": "சனி"},
|
|
74
|
+
"zh": {"full": "星期六", "abbr": "周六"},
|
|
75
|
+
"ja": {"full": "土曜日", "abbr": "土"}
|
|
76
|
+
},
|
|
77
|
+
"SUNDAY": {
|
|
78
|
+
"en": {"full": "Sunday", "abbr": "Sun"},
|
|
79
|
+
"fr": {"full": "Dimanche", "abbr": "Dim"},
|
|
80
|
+
"es": {"full": "Domingo", "abbr": "Dom"},
|
|
81
|
+
"de": {"full": "Sonntag", "abbr": "So"},
|
|
82
|
+
"hi": {"full": "रविवार", "abbr": "रवि"},
|
|
83
|
+
"ar": {"full": "الأحد", "abbr": "أحد"},
|
|
84
|
+
"bn": {"full": "রবিবার", "abbr": "রবি"},
|
|
85
|
+
"ta": {"full": "ஞாயிறு", "abbr": "ஞாயி"},
|
|
86
|
+
"zh": {"full": "星期日", "abbr": "周日"},
|
|
87
|
+
"ja": {"full": "日曜日", "abbr": "日"}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|