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.
Files changed (61) hide show
  1. multilingualprogramming/__init__.py +74 -0
  2. multilingualprogramming/__main__.py +194 -0
  3. multilingualprogramming/codegen/__init__.py +12 -0
  4. multilingualprogramming/codegen/executor.py +215 -0
  5. multilingualprogramming/codegen/python_generator.py +592 -0
  6. multilingualprogramming/codegen/repl.py +489 -0
  7. multilingualprogramming/codegen/runtime_builtins.py +308 -0
  8. multilingualprogramming/core/__init__.py +12 -0
  9. multilingualprogramming/core/ir.py +29 -0
  10. multilingualprogramming/core/lowering.py +24 -0
  11. multilingualprogramming/datetime/__init__.py +11 -0
  12. multilingualprogramming/datetime/date_parser.py +190 -0
  13. multilingualprogramming/datetime/mp_date.py +210 -0
  14. multilingualprogramming/datetime/mp_datetime.py +153 -0
  15. multilingualprogramming/datetime/mp_time.py +147 -0
  16. multilingualprogramming/datetime/resource_loader.py +18 -0
  17. multilingualprogramming/exceptions.py +158 -0
  18. multilingualprogramming/imports.py +150 -0
  19. multilingualprogramming/keyword/__init__.py +13 -0
  20. multilingualprogramming/keyword/keyword_registry.py +249 -0
  21. multilingualprogramming/keyword/keyword_validator.py +59 -0
  22. multilingualprogramming/keyword/language_pack_validator.py +110 -0
  23. multilingualprogramming/lexer/__init__.py +11 -0
  24. multilingualprogramming/lexer/lexer.py +570 -0
  25. multilingualprogramming/lexer/source_reader.py +91 -0
  26. multilingualprogramming/lexer/token.py +54 -0
  27. multilingualprogramming/lexer/token_types.py +38 -0
  28. multilingualprogramming/numeral/__init__.py +11 -0
  29. multilingualprogramming/numeral/abstract_numeral.py +232 -0
  30. multilingualprogramming/numeral/complex_numeral.py +190 -0
  31. multilingualprogramming/numeral/fraction_numeral.py +165 -0
  32. multilingualprogramming/numeral/mp_numeral.py +243 -0
  33. multilingualprogramming/numeral/numeral_converter.py +151 -0
  34. multilingualprogramming/numeral/roman_numeral.py +301 -0
  35. multilingualprogramming/numeral/unicode_numeral.py +292 -0
  36. multilingualprogramming/parser/__init__.py +28 -0
  37. multilingualprogramming/parser/ast_nodes.py +459 -0
  38. multilingualprogramming/parser/ast_printer.py +677 -0
  39. multilingualprogramming/parser/error_messages.py +75 -0
  40. multilingualprogramming/parser/parser.py +1796 -0
  41. multilingualprogramming/parser/semantic_analyzer.py +689 -0
  42. multilingualprogramming/parser/surface_normalizer.py +282 -0
  43. multilingualprogramming/resources/datetime/eras.json +23 -0
  44. multilingualprogramming/resources/datetime/formats.json +32 -0
  45. multilingualprogramming/resources/datetime/months.json +150 -0
  46. multilingualprogramming/resources/datetime/weekdays.json +90 -0
  47. multilingualprogramming/resources/parser/error_messages.json +310 -0
  48. multilingualprogramming/resources/repl/commands.json +636 -0
  49. multilingualprogramming/resources/usm/builtins_aliases.json +731 -0
  50. multilingualprogramming/resources/usm/keywords.json +1063 -0
  51. multilingualprogramming/resources/usm/operators.json +532 -0
  52. multilingualprogramming/resources/usm/schema.json +34 -0
  53. multilingualprogramming/resources/usm/surface_patterns.json +1523 -0
  54. multilingualprogramming/unicode_string.py +140 -0
  55. multilingualprogramming/version.py +9 -0
  56. multilingualprogramming-0.2.0.dist-info/METADATA +350 -0
  57. multilingualprogramming-0.2.0.dist-info/RECORD +61 -0
  58. multilingualprogramming-0.2.0.dist-info/WHEEL +5 -0
  59. multilingualprogramming-0.2.0.dist-info/entry_points.txt +3 -0
  60. multilingualprogramming-0.2.0.dist-info/licenses/LICENSE +674 -0
  61. 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
+ }