ether-code 0.4.7 → 0.4.9
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.
- package/cli/ether.js +1 -1
- package/ether-parser.js +177 -39
- package/generators/js-generator.js +37 -9
- package/i18n/i18n-js.json +1 -9
- package/package.json +1 -1
package/cli/ether.js
CHANGED
package/ether-parser.js
CHANGED
|
@@ -118,9 +118,9 @@ class EtherParser {
|
|
|
118
118
|
'absolu': 'abs',
|
|
119
119
|
'maximum': 'max',
|
|
120
120
|
'minimum': 'min',
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
'maintenant': 'now',
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
'ensemble': 'Set',
|
|
125
125
|
'symbole': 'Symbol',
|
|
126
126
|
'objet': 'Object',
|
|
@@ -297,9 +297,36 @@ class EtherParser {
|
|
|
297
297
|
const token = this.current()
|
|
298
298
|
if (!token || token.value === null || token.value === undefined) return null
|
|
299
299
|
const tokenVal = String(token.value).toLowerCase()
|
|
300
|
-
|
|
300
|
+
const valueLower = value.toLowerCase()
|
|
301
|
+
|
|
302
|
+
if (tokenVal === valueLower) {
|
|
301
303
|
return this.advance()
|
|
302
304
|
}
|
|
305
|
+
|
|
306
|
+
if (valueLower.includes(' ')) {
|
|
307
|
+
const parts = valueLower.split(' ')
|
|
308
|
+
if (tokenVal === parts[0]) {
|
|
309
|
+
const savedPos = this.pos
|
|
310
|
+
const tokens = [this.advance()]
|
|
311
|
+
let matched = true
|
|
312
|
+
|
|
313
|
+
for (let i = 1; i < parts.length && matched; i++) {
|
|
314
|
+
const nextToken = this.current()
|
|
315
|
+
if (nextToken && String(nextToken.value).toLowerCase() === parts[i]) {
|
|
316
|
+
tokens.push(this.advance())
|
|
317
|
+
} else {
|
|
318
|
+
matched = false
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (matched) {
|
|
323
|
+
return tokens[tokens.length - 1]
|
|
324
|
+
} else {
|
|
325
|
+
this.pos = savedPos
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
303
330
|
return null
|
|
304
331
|
}
|
|
305
332
|
|
|
@@ -314,6 +341,27 @@ class EtherParser {
|
|
|
314
341
|
detectTargetLanguage(source) {
|
|
315
342
|
const lower = source.toLowerCase()
|
|
316
343
|
|
|
344
|
+
const targetMatch = source.match(/\/\/\s*cible\s*:\s*(\w+)/i)
|
|
345
|
+
if (targetMatch) {
|
|
346
|
+
const target = targetMatch[1].toLowerCase()
|
|
347
|
+
const langMap = {
|
|
348
|
+
'js': 'js', 'javascript': 'js',
|
|
349
|
+
'css': 'css', 'style': 'css',
|
|
350
|
+
'html': 'html', 'page': 'html',
|
|
351
|
+
'ts': 'ts', 'typescript': 'ts',
|
|
352
|
+
'react': 'react', 'jsx': 'react',
|
|
353
|
+
'php': 'php',
|
|
354
|
+
'python': 'python', 'py': 'python',
|
|
355
|
+
'ruby': 'ruby', 'rb': 'ruby',
|
|
356
|
+
'sql': 'sql',
|
|
357
|
+
'node': 'node', 'nodejs': 'node',
|
|
358
|
+
'graphql': 'graphql', 'gql': 'graphql'
|
|
359
|
+
}
|
|
360
|
+
if (langMap[target]) {
|
|
361
|
+
return langMap[target]
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
317
365
|
if (/^\s*(document|page|<!doctype|<html|tete|corps|entete|navigation|section|article)/m.test(lower)) {
|
|
318
366
|
return 'html'
|
|
319
367
|
}
|
|
@@ -1250,7 +1298,7 @@ class EtherParser {
|
|
|
1250
1298
|
'cesure': 'wbr',
|
|
1251
1299
|
'noscript': 'noscript',
|
|
1252
1300
|
'sans script': 'noscript',
|
|
1253
|
-
|
|
1301
|
+
|
|
1254
1302
|
'zone': 'area'
|
|
1255
1303
|
}
|
|
1256
1304
|
|
|
@@ -1506,6 +1554,47 @@ class EtherParser {
|
|
|
1506
1554
|
}
|
|
1507
1555
|
}
|
|
1508
1556
|
|
|
1557
|
+
parseFunctionExpression(lang) {
|
|
1558
|
+
this.advance()
|
|
1559
|
+
|
|
1560
|
+
let name = null
|
|
1561
|
+
const nameToken = this.current()
|
|
1562
|
+
if (nameToken && nameToken.type === TokenType.IDENTIFIER && !this.check(TokenType.LPAREN)) {
|
|
1563
|
+
const nextToken = this.peek(1)
|
|
1564
|
+
if (nextToken && nextToken.type === TokenType.LPAREN) {
|
|
1565
|
+
name = nameToken.value
|
|
1566
|
+
this.advance()
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
const params = []
|
|
1571
|
+
if (this.match(TokenType.LPAREN)) {
|
|
1572
|
+
while (!this.isAtEnd() && !this.match(TokenType.RPAREN)) {
|
|
1573
|
+
const param = this.parseParameter(lang)
|
|
1574
|
+
if (param) {
|
|
1575
|
+
params.push(param)
|
|
1576
|
+
}
|
|
1577
|
+
this.match(TokenType.COMMA)
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
let returnType = null
|
|
1582
|
+
if (this.match(TokenType.COLON) || this.match(TokenType.ARROW)) {
|
|
1583
|
+
returnType = this.parseType(lang)
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
this.skipNewlines()
|
|
1587
|
+
const body = this.parseBlock(lang)
|
|
1588
|
+
|
|
1589
|
+
return {
|
|
1590
|
+
type: 'FunctionExpression',
|
|
1591
|
+
name: name,
|
|
1592
|
+
params: params,
|
|
1593
|
+
returnType: returnType,
|
|
1594
|
+
body: body
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1509
1598
|
parseParameter(lang) {
|
|
1510
1599
|
const nameToken = this.current()
|
|
1511
1600
|
if (!nameToken || nameToken.type !== TokenType.IDENTIFIER) {
|
|
@@ -1590,7 +1679,7 @@ class EtherParser {
|
|
|
1590
1679
|
'jamais': 'never',
|
|
1591
1680
|
'inconnu': 'unknown',
|
|
1592
1681
|
'symbole': 'symbol',
|
|
1593
|
-
|
|
1682
|
+
|
|
1594
1683
|
'promesse': 'Promise',
|
|
1595
1684
|
'fonction': 'Function'
|
|
1596
1685
|
}
|
|
@@ -1640,8 +1729,10 @@ class EtherParser {
|
|
|
1640
1729
|
}
|
|
1641
1730
|
}
|
|
1642
1731
|
|
|
1643
|
-
parseConditional(lang) {
|
|
1644
|
-
|
|
1732
|
+
parseConditional(lang, isElseIf = false) {
|
|
1733
|
+
if (!isElseIf) {
|
|
1734
|
+
this.advance()
|
|
1735
|
+
}
|
|
1645
1736
|
const condition = this.parseExpression(lang)
|
|
1646
1737
|
|
|
1647
1738
|
this.skipNewlines()
|
|
@@ -1652,7 +1743,7 @@ class EtherParser {
|
|
|
1652
1743
|
|
|
1653
1744
|
if (this.matchValue('sinon')) {
|
|
1654
1745
|
if (this.matchValue('si')) {
|
|
1655
|
-
alternate = this.parseConditional(lang)
|
|
1746
|
+
alternate = this.parseConditional(lang, true)
|
|
1656
1747
|
} else {
|
|
1657
1748
|
this.skipNewlines()
|
|
1658
1749
|
alternate = this.parseBlock(lang)
|
|
@@ -1844,17 +1935,42 @@ class EtherParser {
|
|
|
1844
1935
|
parseBlock(lang) {
|
|
1845
1936
|
const body = []
|
|
1846
1937
|
|
|
1847
|
-
|
|
1938
|
+
const hasBrace = this.match(TokenType.LBRACE)
|
|
1939
|
+
this.skipNewlines()
|
|
1940
|
+
|
|
1941
|
+
if (hasBrace) {
|
|
1942
|
+
this.match(TokenType.INDENT)
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
if (hasBrace || this.match(TokenType.INDENT)) {
|
|
1848
1946
|
while (!this.isAtEnd()) {
|
|
1947
|
+
this.skipNewlines()
|
|
1948
|
+
|
|
1849
1949
|
const current = this.current()
|
|
1850
1950
|
|
|
1851
1951
|
if (current && current.type === TokenType.DEDENT) {
|
|
1852
1952
|
this.advance()
|
|
1953
|
+
if (hasBrace) {
|
|
1954
|
+
this.skipNewlines()
|
|
1955
|
+
this.match(TokenType.RBRACE)
|
|
1956
|
+
}
|
|
1853
1957
|
break
|
|
1854
1958
|
}
|
|
1855
1959
|
|
|
1960
|
+
if (hasBrace && current && current.type === TokenType.RBRACE) {
|
|
1961
|
+
this.advance()
|
|
1962
|
+
break
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
if (current && (current.type === TokenType.INDENT || current.type === TokenType.NEWLINE)) {
|
|
1966
|
+
this.advance()
|
|
1967
|
+
continue
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1856
1970
|
const statement = this.parseStatement(lang)
|
|
1857
|
-
if (statement) {
|
|
1971
|
+
if (statement && statement.expression?.value !== null) {
|
|
1972
|
+
body.push(statement)
|
|
1973
|
+
} else if (statement && statement.type !== 'ExpressionStatement') {
|
|
1858
1974
|
body.push(statement)
|
|
1859
1975
|
}
|
|
1860
1976
|
|
|
@@ -1924,17 +2040,16 @@ class EtherParser {
|
|
|
1924
2040
|
let left = this.parseComparison(lang)
|
|
1925
2041
|
|
|
1926
2042
|
while (true) {
|
|
1927
|
-
|
|
1928
|
-
if (compoundOp === '===' || compoundOp === '!==') {
|
|
2043
|
+
if (this.matchValue('strictement egal') || this.matchValue('strictement égal')) {
|
|
1929
2044
|
const right = this.parseComparison(lang)
|
|
1930
|
-
left = { type: 'BinaryExpression', operator:
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
if (this.match(TokenType.DOUBLE_EQUALS) || this.matchValue('egal') || this.matchValue('egale')) {
|
|
2045
|
+
left = { type: 'BinaryExpression', operator: '===', left, right }
|
|
2046
|
+
} else if (this.matchValue('strictement different') || this.matchValue('strictement différent')) {
|
|
2047
|
+
const right = this.parseComparison(lang)
|
|
2048
|
+
left = { type: 'BinaryExpression', operator: '!==', left, right }
|
|
2049
|
+
} else if (this.match(TokenType.DOUBLE_EQUALS) || this.matchValue('egal') || this.matchValue('egale') || this.matchValue('égal')) {
|
|
1935
2050
|
const right = this.parseComparison(lang)
|
|
1936
2051
|
left = { type: 'BinaryExpression', operator: '===', left, right }
|
|
1937
|
-
} else if (this.match(TokenType.NOT_EQUALS) || this.matchValue('different')) {
|
|
2052
|
+
} else if (this.match(TokenType.NOT_EQUALS) || this.matchValue('different') || this.matchValue('différent')) {
|
|
1938
2053
|
const right = this.parseComparison(lang)
|
|
1939
2054
|
left = { type: 'BinaryExpression', operator: '!==', left, right }
|
|
1940
2055
|
} else {
|
|
@@ -1949,25 +2064,18 @@ class EtherParser {
|
|
|
1949
2064
|
let left = this.parseAdditive(lang)
|
|
1950
2065
|
|
|
1951
2066
|
while (true) {
|
|
1952
|
-
|
|
1953
|
-
if (compoundOp === '>=' || compoundOp === '<=') {
|
|
2067
|
+
if (this.matchValue('superieur ou egal') || this.matchValue('supérieur ou égal') || this.match(TokenType.GTE)) {
|
|
1954
2068
|
const right = this.parseAdditive(lang)
|
|
1955
|
-
left = { type: 'BinaryExpression', operator:
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
if (this.match(TokenType.LT) || this.matchValue('inferieur')) {
|
|
2069
|
+
left = { type: 'BinaryExpression', operator: '>=', left, right }
|
|
2070
|
+
} else if (this.matchValue('inferieur ou egal') || this.matchValue('inférieur ou égal') || this.match(TokenType.LTE)) {
|
|
2071
|
+
const right = this.parseAdditive(lang)
|
|
2072
|
+
left = { type: 'BinaryExpression', operator: '<=', left, right }
|
|
2073
|
+
} else if (this.match(TokenType.LT) || this.matchValue('inferieur') || this.matchValue('inférieur')) {
|
|
1960
2074
|
const right = this.parseAdditive(lang)
|
|
1961
2075
|
left = { type: 'BinaryExpression', operator: '<', left, right }
|
|
1962
|
-
} else if (this.match(TokenType.GT) || this.matchValue('superieur')) {
|
|
2076
|
+
} else if (this.match(TokenType.GT) || this.matchValue('superieur') || this.matchValue('supérieur')) {
|
|
1963
2077
|
const right = this.parseAdditive(lang)
|
|
1964
2078
|
left = { type: 'BinaryExpression', operator: '>', left, right }
|
|
1965
|
-
} else if (this.match(TokenType.LTE)) {
|
|
1966
|
-
const right = this.parseAdditive(lang)
|
|
1967
|
-
left = { type: 'BinaryExpression', operator: '<=', left, right }
|
|
1968
|
-
} else if (this.match(TokenType.GTE)) {
|
|
1969
|
-
const right = this.parseAdditive(lang)
|
|
1970
|
-
left = { type: 'BinaryExpression', operator: '>=', left, right }
|
|
1971
2079
|
} else {
|
|
1972
2080
|
break
|
|
1973
2081
|
}
|
|
@@ -2026,6 +2134,14 @@ class EtherParser {
|
|
|
2026
2134
|
return { type: 'UnaryExpression', operator: '-', operand }
|
|
2027
2135
|
}
|
|
2028
2136
|
|
|
2137
|
+
if (this.matchValue('nouveau') || this.matchValue('new')) {
|
|
2138
|
+
const callee = this.parseCall(lang)
|
|
2139
|
+
if (callee.type === 'CallExpression') {
|
|
2140
|
+
return { type: 'NewExpression', callee: callee.callee, arguments: callee.arguments }
|
|
2141
|
+
}
|
|
2142
|
+
return { type: 'NewExpression', callee, arguments: [] }
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2029
2145
|
return this.parseCall(lang)
|
|
2030
2146
|
}
|
|
2031
2147
|
|
|
@@ -2078,6 +2194,10 @@ class EtherParser {
|
|
|
2078
2194
|
if (token.type === TokenType.IDENTIFIER) {
|
|
2079
2195
|
const value = token.value.toLowerCase()
|
|
2080
2196
|
|
|
2197
|
+
if (value === 'fonction' || value === 'function') {
|
|
2198
|
+
return this.parseFunctionExpression(lang)
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2081
2201
|
if (value === 'vrai' || value === 'true') {
|
|
2082
2202
|
this.advance()
|
|
2083
2203
|
return { type: 'Literal', value: true }
|
|
@@ -2141,26 +2261,32 @@ class EtherParser {
|
|
|
2141
2261
|
this.match(TokenType.COMMA)
|
|
2142
2262
|
}
|
|
2143
2263
|
|
|
2144
|
-
return { type: '
|
|
2264
|
+
return { type: 'ArrayExpression', elements }
|
|
2145
2265
|
}
|
|
2146
2266
|
|
|
2147
2267
|
parseObjectLiteral(lang) {
|
|
2148
2268
|
this.expect(TokenType.LBRACE)
|
|
2149
2269
|
const properties = []
|
|
2150
2270
|
|
|
2151
|
-
|
|
2271
|
+
this.skipWhitespace()
|
|
2272
|
+
|
|
2273
|
+
while (!this.isAtEnd() && !this.check(TokenType.RBRACE)) {
|
|
2274
|
+
this.skipWhitespace()
|
|
2275
|
+
|
|
2152
2276
|
const keyToken = this.current()
|
|
2153
|
-
if (!keyToken) break
|
|
2277
|
+
if (!keyToken || keyToken.type === TokenType.RBRACE) break
|
|
2154
2278
|
|
|
2155
2279
|
let key
|
|
2156
2280
|
if (keyToken.type === TokenType.STRING) {
|
|
2157
|
-
|
|
2281
|
+
const keyValue = keyToken.value.replace(/^["']|["']$/g, '')
|
|
2282
|
+
key = { type: 'Literal', value: keyValue }
|
|
2283
|
+
this.advance()
|
|
2158
2284
|
} else if (keyToken.type === TokenType.IDENTIFIER) {
|
|
2159
|
-
key = keyToken.value
|
|
2285
|
+
key = { type: 'Identifier', name: keyToken.value }
|
|
2286
|
+
this.advance()
|
|
2160
2287
|
} else {
|
|
2161
2288
|
break
|
|
2162
2289
|
}
|
|
2163
|
-
this.advance()
|
|
2164
2290
|
|
|
2165
2291
|
this.match(TokenType.COLON) || this.match(TokenType.EQUALS)
|
|
2166
2292
|
|
|
@@ -2168,9 +2294,21 @@ class EtherParser {
|
|
|
2168
2294
|
properties.push({ key, value })
|
|
2169
2295
|
|
|
2170
2296
|
this.match(TokenType.COMMA)
|
|
2297
|
+
this.skipWhitespace()
|
|
2171
2298
|
}
|
|
2172
2299
|
|
|
2173
|
-
|
|
2300
|
+
this.match(TokenType.RBRACE)
|
|
2301
|
+
|
|
2302
|
+
return { type: 'ObjectExpression', properties }
|
|
2303
|
+
}
|
|
2304
|
+
|
|
2305
|
+
skipWhitespace() {
|
|
2306
|
+
while (this.match(TokenType.NEWLINE) || this.match(TokenType.INDENT) || this.match(TokenType.DEDENT)) {}
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
check(type) {
|
|
2310
|
+
const token = this.current()
|
|
2311
|
+
return token && token.type === type
|
|
2174
2312
|
}
|
|
2175
2313
|
|
|
2176
2314
|
parseSQLProgram() {
|
|
@@ -5,6 +5,9 @@ class JSGenerator {
|
|
|
5
5
|
this.i18n = null
|
|
6
6
|
this.indent = 0
|
|
7
7
|
this.output = ''
|
|
8
|
+
this.keywordMap = {}
|
|
9
|
+
this.methodMap = {}
|
|
10
|
+
this.builtinMap = {}
|
|
8
11
|
|
|
9
12
|
if (i18nPath) {
|
|
10
13
|
this.loadI18n(i18nPath)
|
|
@@ -18,10 +21,6 @@ class JSGenerator {
|
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
buildMaps() {
|
|
21
|
-
this.keywordMap = {}
|
|
22
|
-
this.methodMap = {}
|
|
23
|
-
this.builtinMap = {}
|
|
24
|
-
|
|
25
24
|
if (!this.i18n) return
|
|
26
25
|
|
|
27
26
|
const addToMap = (map, section) => {
|
|
@@ -326,6 +325,8 @@ class JSGenerator {
|
|
|
326
325
|
break
|
|
327
326
|
case 'ArrowFunctionExpression':
|
|
328
327
|
return this.generateArrowFunction(node)
|
|
328
|
+
case 'FunctionExpression':
|
|
329
|
+
return this.generateFunctionExpression(node)
|
|
329
330
|
case 'CallExpression':
|
|
330
331
|
return this.generateCallExpression(node)
|
|
331
332
|
case 'MemberExpression':
|
|
@@ -407,6 +408,28 @@ class JSGenerator {
|
|
|
407
408
|
this.writeLine('')
|
|
408
409
|
}
|
|
409
410
|
|
|
411
|
+
generateFunctionExpression(node) {
|
|
412
|
+
const async = node.async ? 'async ' : ''
|
|
413
|
+
const generator = node.generator ? '*' : ''
|
|
414
|
+
const name = node.name ? this.translate(node.name) : ''
|
|
415
|
+
const params = (node.params || []).map(p => this.generateParameter(p)).join(', ')
|
|
416
|
+
|
|
417
|
+
const bodyStatements = node.body?.body || []
|
|
418
|
+
const bodyCode = bodyStatements.map(stmt => {
|
|
419
|
+
const savedOutput = this.output
|
|
420
|
+
const savedIndent = this.indent
|
|
421
|
+
this.output = ''
|
|
422
|
+
this.indent = 1
|
|
423
|
+
this.generateNode(stmt)
|
|
424
|
+
const stmtCode = this.output.trim()
|
|
425
|
+
this.output = savedOutput
|
|
426
|
+
this.indent = savedIndent
|
|
427
|
+
return stmtCode
|
|
428
|
+
}).join('\n ')
|
|
429
|
+
|
|
430
|
+
return `${async}function${generator}${name ? ' ' + name : ''}(${params}) {\n ${bodyCode}\n }`
|
|
431
|
+
}
|
|
432
|
+
|
|
410
433
|
generateParameter(node) {
|
|
411
434
|
if (!node) return ''
|
|
412
435
|
if (typeof node === 'string') return node
|
|
@@ -466,17 +489,22 @@ class JSGenerator {
|
|
|
466
489
|
this.writeLine('')
|
|
467
490
|
}
|
|
468
491
|
|
|
469
|
-
generateIfStatement(node) {
|
|
470
|
-
const test = this.generateNode(node.test)
|
|
471
|
-
|
|
492
|
+
generateIfStatement(node, isElseIf = false) {
|
|
493
|
+
const test = this.generateNode(node.test || node.condition)
|
|
494
|
+
|
|
495
|
+
if (isElseIf) {
|
|
496
|
+
this.writeLine(`} else if (${test}) {`)
|
|
497
|
+
} else {
|
|
498
|
+
this.writeLine(`if (${test}) {`)
|
|
499
|
+
}
|
|
500
|
+
|
|
472
501
|
this.indent++
|
|
473
502
|
this.generateNode(node.consequent)
|
|
474
503
|
this.indent--
|
|
475
504
|
|
|
476
505
|
if (node.alternate) {
|
|
477
506
|
if (node.alternate.type === 'IfStatement') {
|
|
478
|
-
this.
|
|
479
|
-
this.generateIfStatement(node.alternate)
|
|
507
|
+
this.generateIfStatement(node.alternate, true)
|
|
480
508
|
} else {
|
|
481
509
|
this.writeLine('} else {')
|
|
482
510
|
this.indent++
|
package/i18n/i18n-js.json
CHANGED
|
@@ -158,14 +158,6 @@
|
|
|
158
158
|
"zh": "æ£åˆ™è¡¨è¾¾å¼",
|
|
159
159
|
"ja": "æ£è¦è¡¨ç¾"
|
|
160
160
|
},
|
|
161
|
-
"carte": {
|
|
162
|
-
"fr": "carte",
|
|
163
|
-
"en": "map",
|
|
164
|
-
"es": "mapa",
|
|
165
|
-
"ru": "карта",
|
|
166
|
-
"zh": "æ˜ å°„",
|
|
167
|
-
"ja": "マップ"
|
|
168
|
-
},
|
|
169
161
|
"ensemble": {
|
|
170
162
|
"fr": "ensemble",
|
|
171
163
|
"en": "set",
|
|
@@ -2787,4 +2779,4 @@
|
|
|
2787
2779
|
"ja": "レングス"
|
|
2788
2780
|
}
|
|
2789
2781
|
}
|
|
2790
|
-
}
|
|
2782
|
+
}
|