Skip to content

Commit 56ff140

Browse files
authored
feat: Smarter default language detection (#26)
1 parent f3643c7 commit 56ff140

File tree

9 files changed

+299
-13
lines changed

9 files changed

+299
-13
lines changed

README-ja.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ js-i18n.nvim は、JavaScript の i18n ライブラリをサポートする Neov
9191
```lua
9292
{
9393
primary_language = {}, -- 優先表示する言語(バーチャルテキストなどの表示に使用する言語の初期設定)
94-
translation_source = { "**/locales/*/translation.json" }, -- 翻訳リソースのパターン
95-
detect_language = ..., -- 言語を検出する関数。
94+
translation_source = { "**/{locales,messages}/*.json" }, -- 翻訳リソースのパターン
95+
detect_language = ..., -- 言語を検出する関数。デフォルトではファイル名からヒューリスティックに検出する関数が使用されます。
9696
key_separator = ".", -- キーのセパレータ
9797
virt_text = {
9898
enabled = true, -- バーチャルテキストの表示を有効にする
@@ -113,4 +113,3 @@ js-i18n.nvim は、JavaScript の i18n ライブラリをサポートする Neov
113113

114114
- ライブラリサポートの強化
115115
- namespace のサポート
116-
- 今より賢い翻訳リソースの検出

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ The default settings are as follows. For omitted parts, refer to [config.lua](./
9696
```lua
9797
{
9898
primary_language = {}, -- The default language to display (initial setting for displaying virtual text, etc.)
99-
translation_source = { "**/locales/*/translation.json" }, -- Pattern for translation resources
100-
detect_language = ..., -- Function to detect the language.
99+
translation_source = { "**/{locales,messages}/*.json" }, -- Pattern for translation resources
100+
detect_language = ..., -- Function to detect the language. By default, a function that detects the language heuristically from the file name is used.
101101
key_separator = ".", -- Key separator
102102
virt_text = {
103103
enabled = true, -- Enable virtual text display
@@ -118,4 +118,3 @@ The default settings are as follows. For omitted parts, refer to [config.lua](./
118118

119119
- Enhanced support for libraries
120120
- Namespace support
121-
- Smarter translation resource detection

lua/js-i18n/config.lua

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,32 @@
1+
local langs = require("js-i18n.lang_name_list")
12
local utils = require("js-i18n.utils")
23

34
local M = {}
45

5-
--- ファイルパスから言語を検出する
6-
--- @param path string ファイルパス
7-
local function default_detect_language(path)
6+
local function normalize_lang(locale)
7+
return locale:lower():gsub("-", "_")
8+
end
9+
10+
local LangSet = {}
11+
for _, l in ipairs(langs) do
12+
LangSet[normalize_lang(l)] = true
13+
end
14+
15+
--- Detect language from file path heuristically
16+
--- @param path string File path
17+
function M.default_detect_language(path)
818
local abs_path = vim.fn.fnamemodify(path, ":p")
9-
local split = vim.split(abs_path, "/")
10-
local lang = split[#split - 1]
19+
local split = vim.split(abs_path, "[/.]")
20+
21+
local lang = nil
22+
23+
for _, part in ipairs(vim.fn.reverse(split)) do
24+
if LangSet[normalize_lang(part)] then
25+
lang = part
26+
break
27+
end
28+
end
29+
1130
return lang
1231
end
1332

@@ -56,8 +75,8 @@ end
5675
--- @type I18n.Config
5776
local default_config = {
5877
primary_language = {},
59-
translation_source = { "**/locales/**/*.json" },
60-
detect_language = default_detect_language,
78+
translation_source = { "**/{locales,messages}/*.json" },
79+
detect_language = M.default_detect_language,
6180
key_separator = ".",
6281
virt_text = {
6382
enabled = true,

lua/js-i18n/lang_name_list.lua

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
-- http://tools.ietf.org/html/rfc5646
2+
3+
return {
4+
"af",
5+
"af-ZA",
6+
"ar",
7+
"ar-AE",
8+
"ar-BH",
9+
"ar-DZ",
10+
"ar-EG",
11+
"ar-IQ",
12+
"ar-JO",
13+
"ar-KW",
14+
"ar-LB",
15+
"ar-LY",
16+
"ar-MA",
17+
"ar-OM",
18+
"ar-QA",
19+
"ar-SA",
20+
"ar-SY",
21+
"ar-TN",
22+
"ar-YE",
23+
"az",
24+
"az-AZ",
25+
"az-Cyrl-AZ",
26+
"be",
27+
"be-BY",
28+
"bg",
29+
"bg-BG",
30+
"bs-BA",
31+
"ca",
32+
"ca-ES",
33+
"cs",
34+
"cs-CZ",
35+
"cy",
36+
"cy-GB",
37+
"da",
38+
"da-DK",
39+
"de",
40+
"de-AT",
41+
"de-CH",
42+
"de-DE",
43+
"de-LI",
44+
"de-LU",
45+
"dv",
46+
"dv-MV",
47+
"el",
48+
"el-GR",
49+
"en",
50+
"en-AU",
51+
"en-BZ",
52+
"en-CA",
53+
"en-CB",
54+
"en-GB",
55+
"en-IE",
56+
"en-JM",
57+
"en-NZ",
58+
"en-PH",
59+
"en-TT",
60+
"en-US",
61+
"en-ZA",
62+
"en-ZW",
63+
"eo",
64+
"es",
65+
"es-AR",
66+
"es-BO",
67+
"es-CL",
68+
"es-CO",
69+
"es-CR",
70+
"es-DO",
71+
"es-EC",
72+
"es-ES",
73+
"es-GT",
74+
"es-HN",
75+
"es-MX",
76+
"es-NI",
77+
"es-PA",
78+
"es-PE",
79+
"es-PR",
80+
"es-PY",
81+
"es-SV",
82+
"es-UY",
83+
"es-VE",
84+
"et",
85+
"et-EE",
86+
"eu",
87+
"eu-ES",
88+
"fa",
89+
"fa-IR",
90+
"fi",
91+
"fi-FI",
92+
"fo",
93+
"fo-FO",
94+
"fr",
95+
"fr-BE",
96+
"fr-CA",
97+
"fr-CH",
98+
"fr-FR",
99+
"fr-LU",
100+
"fr-MC",
101+
"gl",
102+
"gl-ES",
103+
"gu",
104+
"gu-IN",
105+
"he",
106+
"he-IL",
107+
"hi",
108+
"hi-IN",
109+
"hr",
110+
"hr-BA",
111+
"hr-HR",
112+
"hu",
113+
"hu-HU",
114+
"hy",
115+
"hy-AM",
116+
"id",
117+
"id-ID",
118+
"is",
119+
"is-IS",
120+
"it",
121+
"it-CH",
122+
"it-IT",
123+
"ja",
124+
"ja-JP",
125+
"ka",
126+
"ka-GE",
127+
"kk",
128+
"kk-KZ",
129+
"kn",
130+
"kn-IN",
131+
"ko",
132+
"ko-KR",
133+
"kok",
134+
"kok-IN",
135+
"ky",
136+
"ky-KG",
137+
"lt",
138+
"lt-LT",
139+
"lv",
140+
"lv-LV",
141+
"mi",
142+
"mi-NZ",
143+
"mk",
144+
"mk-MK",
145+
"mn",
146+
"mn-MN",
147+
"mr",
148+
"mr-IN",
149+
"ms",
150+
"ms-BN",
151+
"ms-MY",
152+
"mt",
153+
"mt-MT",
154+
"nb",
155+
"nb-NO",
156+
"nl",
157+
"nl-BE",
158+
"nl-NL",
159+
"nn-NO",
160+
"ns",
161+
"ns-ZA",
162+
"pa",
163+
"pa-IN",
164+
"pl",
165+
"pl-PL",
166+
"ps",
167+
"ps-AR",
168+
"pt",
169+
"pt-BR",
170+
"pt-PT",
171+
"qu",
172+
"qu-BO",
173+
"qu-EC",
174+
"qu-PE",
175+
"ro",
176+
"ro-RO",
177+
"ru",
178+
"ru-RU",
179+
"sa",
180+
"sa-IN",
181+
"se",
182+
"se-FI",
183+
"se-NO",
184+
"se-SE",
185+
"sk",
186+
"sk-SK",
187+
"sl",
188+
"sl-SI",
189+
"sq",
190+
"sq-AL",
191+
"sr-BA",
192+
"sr-Cyrl-BA",
193+
"sr-SP",
194+
"sr-Cyrl-SP",
195+
"sv",
196+
"sv-FI",
197+
"sv-SE",
198+
"sw",
199+
"sw-KE",
200+
"syr",
201+
"syr-SY",
202+
"ta",
203+
"ta-IN",
204+
"te",
205+
"te-IN",
206+
"th",
207+
"th-TH",
208+
"tl",
209+
"tl-PH",
210+
"tn",
211+
"tn-ZA",
212+
"tr",
213+
"tr-TR",
214+
"tt",
215+
"tt-RU",
216+
"ts",
217+
"uk",
218+
"uk-UA",
219+
"ur",
220+
"ur-PK",
221+
"uz",
222+
"uz-UZ",
223+
"uz-Cyrl-UZ",
224+
"vi",
225+
"vi-VN",
226+
"xh",
227+
"xh-ZA",
228+
"zh",
229+
"zh-CN",
230+
"zh-HK",
231+
"zh-MO",
232+
"zh-SG",
233+
"zh-TW",
234+
"zu",
235+
"zu-ZA",
236+
}

tests/js-i18n/config_spec.lua

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
local config = require("js-i18n.config")
2+
3+
describe("js-i18n.config", function()
4+
describe("default_detect_language", function()
5+
local tests = {
6+
{ path = "/path/to/locals/en/trans.json", expected = "en" },
7+
{ path = "/path/to/locals/ja/trans.json", expected = "ja" },
8+
{ path = "/path/to/locals/hoge/trans.json", expected = nil },
9+
10+
-- Test cases to verify that it is sufficient for the languagee name to be included somewhere.
11+
{ path = "/path/to/locals/sub/en.json", expected = "en" },
12+
{ path = "/path/to/en/locals/trans.json", expected = "en" },
13+
{ path = "/path/to/locals/en-trans.json", expected = nil },
14+
15+
-- Test cases for language names with any case and separating characters.
16+
{ path = "/path/to/locals/en-us/trans.json", expected = "en-us" },
17+
{ path = "/path/to/locals/en_us/trans.json", expected = "en_us" },
18+
{ path = "/path/to/locals/en-US/trans.json", expected = "en-US" },
19+
20+
-- Test cases where the last match is returned when multiple locale names are included.
21+
{ path = "/path/to/locals/en/ja.json", expected = "ja" },
22+
}
23+
24+
for _, test in ipairs(tests) do
25+
it(
26+
string.format("should return %q when detecting language from %q", test.expected, test.path),
27+
function()
28+
assert.are.equal(test.expected, config.default_detect_language(test.path))
29+
end
30+
)
31+
end
32+
end)
33+
end)

0 commit comments

Comments
 (0)