aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xscripts/i18n/pull-hook.sh12
-rwxr-xr-xscripts/i18n/xliff2json.ts179
-rw-r--r--support/doc/translation.md22
-rw-r--r--zanata.xml15
4 files changed, 12 insertions, 216 deletions
diff --git a/scripts/i18n/pull-hook.sh b/scripts/i18n/pull-hook.sh
deleted file mode 100755
index 66f3b4588..000000000
--- a/scripts/i18n/pull-hook.sh
+++ /dev/null
@@ -1,12 +0,0 @@
1#!/bin/sh
2
3set -eu
4
5for i in $(seq 1 10); do
6 # Zanata does not support inner elements in <source>, so we hack these special elements
7 # This regex translate the converted elements to initial Angular elements
8 perl -pi -e 's|&lt;x id=(.+?)/&gt;([^"])|<x id=\1/>\2|g' client/src/locale/target/*.xml
9done
10
11npm run i18n:xliff2json
12
diff --git a/scripts/i18n/xliff2json.ts b/scripts/i18n/xliff2json.ts
deleted file mode 100755
index d15039bb9..000000000
--- a/scripts/i18n/xliff2json.ts
+++ /dev/null
@@ -1,179 +0,0 @@
1import { registerTSPaths } from '../../server/helpers/register-ts-paths'
2registerTSPaths()
3
4import * as xliff12ToJs from 'xliff/xliff12ToJs'
5import { readFileSync, readJSON, unlink, writeFile, writeJSON, existsSync, exists, pathExists } from 'fs-extra'
6import { join } from 'path'
7import { buildFileLocale, I18N_LOCALES, isDefaultLocale } from '../../shared/models/i18n/i18n'
8import { eachSeries } from 'async'
9
10const sources: string[] = []
11const l = [
12 'ar-001',
13 'ca-ES',
14 'cs-CZ',
15 'da-DK',
16 'de-DE',
17 'el-GR',
18 'en-GB',
19 'en-US',
20 'eo',
21 'es-ES',
22 'eu-ES',
23 'fa-IR',
24 'fi-FI',
25 'fr-FR',
26 'gd',
27 'gl-ES',
28 'hu-HU',
29 'it-IT',
30 'ja-JP',
31 'jbo',
32 'ko-KR',
33 'lt-LT',
34 'nb-NO',
35 'nl-NL',
36 'oc',
37 'pl-PL',
38 'pt-BR',
39 'pt-PT',
40 'ru-RU',
41 'sk-SK',
42 'sl-SI',
43 'sv-SE',
44 'ta',
45 'th-TH',
46 'tr-TR',
47 'uk-UA',
48 'vi-VN',
49 'zh-Hans-CN',
50 'zh-Hant-TW'
51]
52
53const availableLocales = l.filter(l => isDefaultLocale(l) === false)
54 .map(l => buildFileLocale(l))
55
56for (const file of [ 'player', 'server', 'iso639' ]) {
57 for (const locale of availableLocales) {
58 sources.push(join(__dirname, '../../../client/src/locale/target/', `${file}_${locale}.xml`))
59 }
60}
61
62eachSeries(sources, (source, cb) => {
63 xliffFile2JSON(source, cb)
64}, err => {
65 if (err) return handleError(err)
66
67 mergeISO639InServer(err => {
68 if (err) return handleError(err)
69
70 injectMissingTranslations().then(() => process.exit(0))
71 })
72})
73
74function handleError (err: any) {
75 console.error(err)
76 process.exit(-1)
77}
78
79function xliffFile2JSON (filePath: string, cb) {
80 const fileTarget = filePath.replace('.xml', '.json')
81
82 if (!existsSync(filePath)) {
83 console.log('No file %s exists.', filePath)
84 return cb()
85 }
86
87 // Remove the two first lines our xliff module does not like
88 let fileContent = readFileSync(filePath).toString()
89 fileContent = removeFirstLine(fileContent)
90 fileContent = removeFirstLine(fileContent)
91
92 xliff12ToJs(fileContent, (err, res) => {
93 if (err) return cb(err)
94
95 const json = createJSONString(res)
96 writeFile(fileTarget, json, err => {
97 if (err) return cb(err)
98
99 return unlink(filePath, cb)
100 })
101 })
102}
103
104function mergeISO639InServer (cb) {
105 eachSeries(availableLocales, (locale, eachCallback) => {
106 const serverPath = join(__dirname, '../../../client/src/locale/target/', `server_${locale}.json`)
107 const iso639Path = join(__dirname, '../../../client/src/locale/target/', `iso639_${locale}.json`)
108
109 if (!existsSync(serverPath)) {
110 console.log('No file %s exists.', serverPath)
111 return cb()
112 }
113 if (!existsSync(iso639Path)) {
114 console.log('No file %s exists.', iso639Path)
115 return cb()
116 }
117
118 const resServer = readFileSync(serverPath).toString()
119 const resISO639 = readFileSync(iso639Path).toString()
120
121 const jsonServer = JSON.parse(resServer)
122 const jsonISO639 = JSON.parse(resISO639)
123
124 Object.assign(jsonServer, jsonISO639)
125 const serverString = JSON.stringify(jsonServer)
126
127 writeFile(serverPath, serverString, err => {
128 if (err) return eachCallback(err)
129
130 return unlink(iso639Path, eachCallback)
131 })
132 }, cb)
133}
134
135function removeFirstLine (str: string) {
136 return str.substring(str.indexOf('\n') + 1)
137}
138
139function createJSONString (obj: any) {
140 const res: any = {}
141 const strings = obj.resources['']
142
143 Object.keys(strings).forEach(k => res[k] = strings[k].target)
144
145 return JSON.stringify(res)
146}
147
148async function injectMissingTranslations () {
149 const baseServer = await readJSON(join(__dirname, '../../../client/src/locale/server.en-US.json'))
150 Object.keys(baseServer).forEach(k => baseServer[k] = '')
151
152 for (const locale of availableLocales) {
153 const serverPath = join(__dirname, '../../../client/src/locale/target/', `server_${locale}.json`)
154 if (!await pathExists(serverPath)) {
155 console.log('No file exists to inject missing translations: %s.', serverPath)
156 continue
157 }
158
159 let serverJSON = await readJSON(serverPath)
160
161 serverJSON = Object.assign({}, baseServer, serverJSON)
162 await writeJSON(serverPath, serverJSON)
163 }
164
165 const basePlayer = await readJSON(join(__dirname, '../../../client/src/locale/player.en-US.json'))
166 Object.keys(basePlayer).forEach(k => basePlayer[k] = '')
167 for (const locale of availableLocales) {
168 const serverPath = join(__dirname, '../../../client/src/locale/target/', `player_${locale}.json`)
169 if (!await pathExists(serverPath)) {
170 console.log('No file exists to inject missing translations: %s.', serverPath)
171 continue
172 }
173
174 let serverJSON = await readJSON(serverPath)
175
176 serverJSON = Object.assign({}, basePlayer, serverJSON)
177 await writeJSON(serverPath, serverJSON)
178 }
179}
diff --git a/support/doc/translation.md b/support/doc/translation.md
index 58b52f5f8..1a3e59f9f 100644
--- a/support/doc/translation.md
+++ b/support/doc/translation.md
@@ -1,17 +1,19 @@
1# Translation 1# Translation
2 2
3We use [Zanata](http://zanata.org/) as translation platform. 3We use [Weblate](https://weblate.org) as translation platform.
4Please do not edit xml files directly from Git, you have to use Zanata! 4Please do not edit translation files directly from Git, you have to use Weblate!
5 5
6If you don't see your locale in the platform, please [create an issue](https://github.com/Chocobozzz/PeerTube/issues) so we add it! 6If you don't see your locale in the platform you can add it directly in the Weblate interface.
7Then, if you think there are enough translated strings, please [create an issue](https://github.com/Chocobozzz/PeerTube/issues) so we add the new locale in PeerTube!
7 8
8 9
9## How to 10## How to
10 11
11 * Create an account: https://trad.framasoft.org/account/register 12 * Create an account: https://weblate.framasoft.org/accounts/register/
12 * Join a language team: https://trad.framasoft.org/languages 13 * Validate your email and follow the link sent
13 * Go to the PeerTube page https://trad.framasoft.org/iteration/view/peertube/develop 14 * Create your password (keep the `Current password` field empty) and setup your account
14 * Choose the locale and begin to translate PeerTube! 15 * Go to the PeerTube page https://weblate.framasoft.org/projects/peertube/
16 * Choose the file and the locale you want to translate
15 17
16 18
17## Files 19## Files
@@ -20,10 +22,10 @@ There are 4 files:
20 * **angular**: contains client strings 22 * **angular**: contains client strings
21 * **player**: contains player strings. 23 * **player**: contains player strings.
22 Most of the strings come from VideoJS, so you can help yourself by using [video.js JSON files](https://github.com/videojs/video.js/tree/master/lang) 24 Most of the strings come from VideoJS, so you can help yourself by using [video.js JSON files](https://github.com/videojs/video.js/tree/master/lang)
23 * **server**: contains server strings (privacies, licences...) 25 * **server**: contains server strings (privacies, licences...) and iso639 (languages) strings used by PeerTube to describe the audio language of a particular video.
24 * **iso639**: contains iso639 (languages) strings used by PeerTube to describe the audio language of a particular video.
25 It's the reason why these strings should be translated too. There are many strings so do not hesitate to translate only main audio languages. 26 It's the reason why these strings should be translated too. There are many strings so do not hesitate to translate only main audio languages.
26 27
28
27## Tips 29## Tips
28 30
29### Special tags 31### Special tags
@@ -39,7 +41,7 @@ should be in french
39 41
40### Singular/plural 42### Singular/plural
41 43
42For singular/plural translations, you must translate values inside `{` and `}`. 44For singular/plural translations, you must translate values inside `{` and `}`. **Please don't translate the word *other***
43 45
44For example: 46For example:
45 47
diff --git a/zanata.xml b/zanata.xml
deleted file mode 100644
index f1148cd6e..000000000
--- a/zanata.xml
+++ /dev/null
@@ -1,15 +0,0 @@
1<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
2<config xmlns="http://zanata.org/namespace/config/">
3 <url>https://trad.framasoft.org/</url>
4 <project>peertube</project>
5 <project-version>develop</project-version>
6 <project-type>xliff</project-type>
7 <src-dir>./client/src/locale/source</src-dir>
8 <trans-dir>./client/src/locale/target</trans-dir>
9
10 <hooks>
11 <hook command="pull">
12 <after>./scripts/i18n/pull-hook.sh</after>
13 </hook>
14 </hooks>
15</config>