Skip to content

Commit

Permalink
feat: Smarter default language detection (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
nabekou29 authored Sep 7, 2024
1 parent f3643c7 commit 56ff140
Show file tree
Hide file tree
Showing 9 changed files with 299 additions and 13 deletions.
5 changes: 2 additions & 3 deletions README-ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ js-i18n.nvim は、JavaScript の i18n ライブラリをサポートする Neov
```lua
{
primary_language = {}, -- 優先表示する言語(バーチャルテキストなどの表示に使用する言語の初期設定)
translation_source = { "**/locales/*/translation.json" }, -- 翻訳リソースのパターン
detect_language = ..., -- 言語を検出する関数。
translation_source = { "**/{locales,messages}/*.json" }, -- 翻訳リソースのパターン
detect_language = ..., -- 言語を検出する関数。デフォルトではファイル名からヒューリスティックに検出する関数が使用されます。
key_separator = ".", -- キーのセパレータ
virt_text = {
enabled = true, -- バーチャルテキストの表示を有効にする
Expand All @@ -113,4 +113,3 @@ js-i18n.nvim は、JavaScript の i18n ライブラリをサポートする Neov

- ライブラリサポートの強化
- namespace のサポート
- 今より賢い翻訳リソースの検出
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ The default settings are as follows. For omitted parts, refer to [config.lua](./
```lua
{
primary_language = {}, -- The default language to display (initial setting for displaying virtual text, etc.)
translation_source = { "**/locales/*/translation.json" }, -- Pattern for translation resources
detect_language = ..., -- Function to detect the language.
translation_source = { "**/{locales,messages}/*.json" }, -- Pattern for translation resources
detect_language = ..., -- Function to detect the language. By default, a function that detects the language heuristically from the file name is used.
key_separator = ".", -- Key separator
virt_text = {
enabled = true, -- Enable virtual text display
Expand All @@ -118,4 +118,3 @@ The default settings are as follows. For omitted parts, refer to [config.lua](./

- Enhanced support for libraries
- Namespace support
- Smarter translation resource detection
File renamed without changes.
File renamed without changes.
33 changes: 26 additions & 7 deletions lua/js-i18n/config.lua
Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@
local langs = require("js-i18n.lang_name_list")
local utils = require("js-i18n.utils")

local M = {}

--- ファイルパスから言語を検出する
--- @param path string ファイルパス
local function default_detect_language(path)
local function normalize_lang(locale)
return locale:lower():gsub("-", "_")
end

local LangSet = {}
for _, l in ipairs(langs) do
LangSet[normalize_lang(l)] = true
end

--- Detect language from file path heuristically
--- @param path string File path
function M.default_detect_language(path)
local abs_path = vim.fn.fnamemodify(path, ":p")
local split = vim.split(abs_path, "/")
local lang = split[#split - 1]
local split = vim.split(abs_path, "[/.]")

local lang = nil

for _, part in ipairs(vim.fn.reverse(split)) do
if LangSet[normalize_lang(part)] then
lang = part
break
end
end

return lang
end

Expand Down Expand Up @@ -56,8 +75,8 @@ end
--- @type I18n.Config
local default_config = {
primary_language = {},
translation_source = { "**/locales/**/*.json" },
detect_language = default_detect_language,
translation_source = { "**/{locales,messages}/*.json" },
detect_language = M.default_detect_language,
key_separator = ".",
virt_text = {
enabled = true,
Expand Down
236 changes: 236 additions & 0 deletions lua/js-i18n/lang_name_list.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
-- http://tools.ietf.org/html/rfc5646

return {
"af",
"af-ZA",
"ar",
"ar-AE",
"ar-BH",
"ar-DZ",
"ar-EG",
"ar-IQ",
"ar-JO",
"ar-KW",
"ar-LB",
"ar-LY",
"ar-MA",
"ar-OM",
"ar-QA",
"ar-SA",
"ar-SY",
"ar-TN",
"ar-YE",
"az",
"az-AZ",
"az-Cyrl-AZ",
"be",
"be-BY",
"bg",
"bg-BG",
"bs-BA",
"ca",
"ca-ES",
"cs",
"cs-CZ",
"cy",
"cy-GB",
"da",
"da-DK",
"de",
"de-AT",
"de-CH",
"de-DE",
"de-LI",
"de-LU",
"dv",
"dv-MV",
"el",
"el-GR",
"en",
"en-AU",
"en-BZ",
"en-CA",
"en-CB",
"en-GB",
"en-IE",
"en-JM",
"en-NZ",
"en-PH",
"en-TT",
"en-US",
"en-ZA",
"en-ZW",
"eo",
"es",
"es-AR",
"es-BO",
"es-CL",
"es-CO",
"es-CR",
"es-DO",
"es-EC",
"es-ES",
"es-GT",
"es-HN",
"es-MX",
"es-NI",
"es-PA",
"es-PE",
"es-PR",
"es-PY",
"es-SV",
"es-UY",
"es-VE",
"et",
"et-EE",
"eu",
"eu-ES",
"fa",
"fa-IR",
"fi",
"fi-FI",
"fo",
"fo-FO",
"fr",
"fr-BE",
"fr-CA",
"fr-CH",
"fr-FR",
"fr-LU",
"fr-MC",
"gl",
"gl-ES",
"gu",
"gu-IN",
"he",
"he-IL",
"hi",
"hi-IN",
"hr",
"hr-BA",
"hr-HR",
"hu",
"hu-HU",
"hy",
"hy-AM",
"id",
"id-ID",
"is",
"is-IS",
"it",
"it-CH",
"it-IT",
"ja",
"ja-JP",
"ka",
"ka-GE",
"kk",
"kk-KZ",
"kn",
"kn-IN",
"ko",
"ko-KR",
"kok",
"kok-IN",
"ky",
"ky-KG",
"lt",
"lt-LT",
"lv",
"lv-LV",
"mi",
"mi-NZ",
"mk",
"mk-MK",
"mn",
"mn-MN",
"mr",
"mr-IN",
"ms",
"ms-BN",
"ms-MY",
"mt",
"mt-MT",
"nb",
"nb-NO",
"nl",
"nl-BE",
"nl-NL",
"nn-NO",
"ns",
"ns-ZA",
"pa",
"pa-IN",
"pl",
"pl-PL",
"ps",
"ps-AR",
"pt",
"pt-BR",
"pt-PT",
"qu",
"qu-BO",
"qu-EC",
"qu-PE",
"ro",
"ro-RO",
"ru",
"ru-RU",
"sa",
"sa-IN",
"se",
"se-FI",
"se-NO",
"se-SE",
"sk",
"sk-SK",
"sl",
"sl-SI",
"sq",
"sq-AL",
"sr-BA",
"sr-Cyrl-BA",
"sr-SP",
"sr-Cyrl-SP",
"sv",
"sv-FI",
"sv-SE",
"sw",
"sw-KE",
"syr",
"syr-SY",
"ta",
"ta-IN",
"te",
"te-IN",
"th",
"th-TH",
"tl",
"tl-PH",
"tn",
"tn-ZA",
"tr",
"tr-TR",
"tt",
"tt-RU",
"ts",
"uk",
"uk-UA",
"ur",
"ur-PK",
"uz",
"uz-UZ",
"uz-Cyrl-UZ",
"vi",
"vi-VN",
"xh",
"xh-ZA",
"zh",
"zh-CN",
"zh-HK",
"zh-MO",
"zh-SG",
"zh-TW",
"zu",
"zu-ZA",
}
33 changes: 33 additions & 0 deletions tests/js-i18n/config_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
local config = require("js-i18n.config")

describe("js-i18n.config", function()
describe("default_detect_language", function()
local tests = {
{ path = "/path/to/locals/en/trans.json", expected = "en" },
{ path = "/path/to/locals/ja/trans.json", expected = "ja" },
{ path = "/path/to/locals/hoge/trans.json", expected = nil },

-- Test cases to verify that it is sufficient for the languagee name to be included somewhere.
{ path = "/path/to/locals/sub/en.json", expected = "en" },
{ path = "/path/to/en/locals/trans.json", expected = "en" },
{ path = "/path/to/locals/en-trans.json", expected = nil },

-- Test cases for language names with any case and separating characters.
{ path = "/path/to/locals/en-us/trans.json", expected = "en-us" },
{ path = "/path/to/locals/en_us/trans.json", expected = "en_us" },
{ path = "/path/to/locals/en-US/trans.json", expected = "en-US" },

-- Test cases where the last match is returned when multiple locale names are included.
{ path = "/path/to/locals/en/ja.json", expected = "ja" },
}

for _, test in ipairs(tests) do
it(
string.format("should return %q when detecting language from %q", test.expected, test.path),
function()
assert.are.equal(test.expected, config.default_detect_language(test.path))
end
)
end
end)
end)
File renamed without changes.
File renamed without changes.

0 comments on commit 56ff140

Please sign in to comment.