embedded languages
Massimo Melina committed
Apr 5, 2023 at 15:29 UTC
e5c067b51302d6a1eadd04c93dc12a829694d838
11 files changed
+41
-19
README.md
+4
-7
@@ -84,15 +84,12 @@ If you want to run HFS as a service
84
## Internationalization
85
86
It is possible to show the Front-end in other languages.
87
-In the Languages section of the Admin-panel you'll be able to install lang files.
88
-You can find some of these files at https://github.com/rejetto/hfs/tree/main/langs
89
-Files are named `hfs-lang-CODE.json`, where `CODE` is the ISO code for your language (e.g. pt-br for Brazilian).
90
-To download a file: open it, right-click on the "Raw" button, Save.
87
+Translation for some languages is already provided. If you find an error, consider reporting it
88
+or [editing the source file](https://github.com/rejetto/hfs/tree/main/src/langs).
89
92
-If your language is missing, please consider [translating yourself](https://github.com/rejetto/hfs/wiki/Translation).
90
+In the Languages section of the Admin-panel you can install additional language files.
91
94
-Translation is applied automatically based on the configuration of the visitor's browser.
95
-[Check the language configuration of your browser](https://gtranslate.io/detect-browser-language).
92
+If your language is missing, please consider [translating yourself](https://github.com/rejetto/hfs/wiki/Translation).
93
94
## Plug-ins
95
admin/src/LangPage.ts
+6
-2
@@ -22,7 +22,7 @@ export default function LangPage() {
22
h(Box, { mb: 1, display: 'flex' },
23
h(Button, { variant: 'contained', startIcon: h(Upload), onClick: add }, "Add"),
24
h(Box, { flex: 1 }),
25
- h(ForceLang, { langs: list.map(x => x.code) }),
25
+ h(ForceLang, { langs: _.uniq(list.map(x => x.code)) }),
26
),
27
h(DataGrid, {
28
loading: connecting,
@@ -38,6 +38,10 @@ export default function LangPage() {
38
field: 'version',
39
width: 80,
40
},
41
+ {
42
+ field: 'hfs_version',
43
+ headerName: "HFS version",
44
+ },
45
{
46
field: 'author',
47
flex: 1,
@@ -49,7 +53,7 @@ export default function LangPage() {
53
hideSortIcons: true,
54
disableColumnMenu: true,
55
renderCell({ row }) {
52
- return h('div', {},
56
+ return row.embedded ? "Embedded" : h('div', {},
57
h(IconBtn, {
58
icon: Delete,
59
title: "Delete",
src/api.lang.ts
+3
-1
@@ -6,7 +6,7 @@ import glob from 'fast-glob'
6
import { readFile, rm, writeFile } from 'fs/promises'
7
import { HTTP_BAD_REQUEST, HTTP_NOT_ACCEPTABLE, HTTP_SERVER_ERROR } from './const'
8
import { tryJson } from './misc'
9
-import { code2file, file2code } from './lang'
9
+import { code2file, EMBEDDED_TRANSLATIONS, file2code } from './lang'
10
11
const apis: ApiHandlers = {
12
@@ -22,6 +22,8 @@ const apis: ApiHandlers = {
22
}
23
catch {}
24
}
25
+ for (const [code, data] of Object.entries(EMBEDDED_TRANSLATIONS))
26
+ list.add({ code, embedded: true, ..._.omit(data, 'translate') })
27
list.close()
28
}
29
})
src/lang.ts
+26
-7
@@ -6,7 +6,7 @@ import { watchLoad } from './watchLoad'
6
7
const PREFIX = 'hfs-lang-'
8
const SUFFIX = '.json'
9
-const EMBEDDED = 'en'
9
+const EMBEDDED_LANGUAGE = 'en'
10
11
export function code2file(code: string) {
12
return PREFIX + code.toLowerCase() + SUFFIX
@@ -25,14 +25,18 @@ export async function getLangData(ctx: Koa.Context) {
25
let i = 0
26
while (i < langs.length) {
27
let k = langs[i] || '' // shut up ts
28
- if (!k || k === EMBEDDED) break
28
+ if (!k || k === EMBEDDED_LANGUAGE) break
29
try { ret[k!] = JSON.parse(await readFile(`hfs-lang-${k}.json`, 'utf8')) }
30
catch {
31
- do { k = k.substring(0, k.lastIndexOf('-'))
32
- } while (k && langs.includes(k))
33
- if (k) {
34
- langs[i] = k // overwrite and retry
35
- continue
31
+ if (k in EMBEDDED_TRANSLATIONS)
32
+ ret[k] = EMBEDDED_TRANSLATIONS[k as keyof typeof EMBEDDED_TRANSLATIONS]
33
+ else {
34
+ do { k = k.substring(0, k.lastIndexOf('-'))
35
+ } while (k && langs.includes(k))
36
+ if (k) {
37
+ langs[i] = k // overwrite and retry
38
+ continue
39
+ }
40
}
41
}
42
i++
@@ -52,3 +56,18 @@ defineConfig('force_lang', '', v => {
56
undo = res.unwatch
57
})
58
59
+
60
+import lang_it from './langs/hfs-lang-it.json'
61
+import lang_zh from './langs/hfs-lang-zh.json'
62
+import lang_ru from './langs/hfs-lang-ru.json'
63
+import lang_sr from './langs/hfs-lang-sr.json'
64
+import lang_ko from './langs/hfs-lang-ko.json'
65
+
66
+export const EMBEDDED_TRANSLATIONS = {
67
+ it: lang_it,
68
+ zh: lang_zh,
69
+ ru: lang_ru,
70
+ sr: lang_sr,
71
+ ko: lang_ko,
72
+}
73
+
src/langs/hfs-lang-en.json
renamed
src/langs/hfs-lang-it.json
renamed
src/langs/hfs-lang-ko.json
renamed
+1
-1
@@ -4,7 +4,7 @@
4
"hfs_version": "0.42.3",
5
"translate": {
6
"Select": "선택",
7
- "n_files": "{n,개의 파일,{# file} other{# files}}",
7
+ "n_files": "{n,plural,one{1개의 파일} =2 =3{파일 #개} other{#개 파일}}",
8
"n_folders": "{n,개의 폴더,{# folder} other{# folders}}",
9
"filter_count": "{n,개, {# filtered} other{# filtered}}",
10
"select_count": "{n,개, {# selected} other{# selected}}",
src/langs/hfs-lang-ru.json
renamed
src/langs/hfs-lang-sr.json
renamed
src/langs/hfs-lang-zh.json
renamed
tsconfig.json
+1
-1
@@ -34,7 +34,7 @@
34
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
35
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
36
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
37
- // "resolveJsonModule": true, /* Enable importing .json files */
37
+ "resolveJsonModule": true, /* Enable importing .json files */
38
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
39
40
/* JavaScript Support */