diff --git a/.gitignore b/.gitignore index ee2ed95e2..548cfd7b3 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,5 @@ docs/_build data/ .env + +po/*.po diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 94b40bed3..217047794 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -68,6 +68,8 @@ build_front: script: - yarn install + - yarn run i18n-extract + - yarn run i18n-compile - yarn run build cache: key: "$CI_PROJECT_ID__front_dependencies" diff --git a/README.rst b/README.rst index 747a1e220..8a0ea4932 100644 --- a/README.rst +++ b/README.rst @@ -208,6 +208,17 @@ Typical workflow for a merge request 8. Take a step back and enjoy, we're really grateful you did all of this and took the time to contribute! +Internationalization +-------------------- + +When working on the front-end, any end-user string should be translated +using either ```` or the ``$t('yourstring')`` +function. + +Extraction is done by calling ``yarn run i18n-extract``, which +will pull all the strings from source files and put them in a PO file. + + Working with federation locally ------------------------------- @@ -245,7 +256,7 @@ Run a reverse proxy for your instances ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Crete docker network +Create docker network ^^^^^^^^^^^^^^^^^^^^ Create the federation network:: @@ -265,7 +276,7 @@ need:: export COMPOSE_PROJECT_NAME=node2 docker-compose -f dev.yml run --rm api python manage.py migrate docker-compose -f dev.yml run --rm api python manage.py createsuperuser - docker-compose -f dev.yml up nginx api front + docker-compose -f dev.yml up nginx api front nginx api celeryworker Note that by default, if you don't export the COMPOSE_PROJECT_NAME, we will default to node1 as the name of your instance. diff --git a/changes/changelog.d/162-script.enhancement b/changes/changelog.d/162-script.enhancement new file mode 100644 index 000000000..ac501a0a9 --- /dev/null +++ b/changes/changelog.d/162-script.enhancement @@ -0,0 +1 @@ +Added a i18n-extract yarn script to extract strings to PO files (#162) diff --git a/front/build/i18n.js b/front/build/i18n.js index 8739d06d2..ef31070c7 100644 --- a/front/build/i18n.js +++ b/front/build/i18n.js @@ -29,6 +29,17 @@ fs.readdir(poDir, (err, files) => { console.log(err) } else { console.log(`Wrote translation file: ${output}`) + if (lang === 'en') { + // for english, we need to specify that json values are equal to the keys. + // otherwise we end up with empty strings on the front end for english + var contents = fs.readFileSync(output) + var jsonContent = JSON.parse(contents) + var finalContent = {} + Object.keys(jsonContent).forEach(function(key) { + finalContent[key] = key + }) + fs.writeFile(output, JSON.stringify(finalContent)) + } } }) }) @@ -36,4 +47,3 @@ fs.readdir(poDir, (err, files) => { } } }) - diff --git a/front/package.json b/front/package.json index e480008c6..8844e8bee 100644 --- a/front/package.json +++ b/front/package.json @@ -8,6 +8,8 @@ "dev": "node build/dev-server.js", "start": "node build/dev-server.js", "build": "node build/build.js", + "i18n-extract": "find src/ -name '*.vue' | xargs vendor/vue-i18n-xgettext/index.js > ../po/en.po", + "i18n-compile": "node build/i18n.js", "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", "unit-watch": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js", "e2e": "node test/e2e/runner.js", @@ -102,6 +104,7 @@ "sinon-chai": "^2.8.0", "sinon-stub-promise": "^4.0.0", "url-loader": "^0.5.8", + "vue-i18n-xgettext": "^0.0.4", "vue-loader": "^12.1.0", "vue-style-loader": "^3.0.1", "vue-template-compiler": "^2.3.3", diff --git a/front/src/components/auth/Settings.vue b/front/src/components/auth/Settings.vue index 64f7df714..c847bde88 100644 --- a/front/src/components/auth/Settings.vue +++ b/front/src/components/auth/Settings.vue @@ -80,16 +80,16 @@ export default { 'privacy_level': { type: 'dropdown', initial: this.$store.state.auth.profile.privacy_level, - label: this.$t('Activity visibility'), - help: this.$t('Determine the visibility level of your activity'), + label: 'Activity visibility', + help: 'Determine the visibility level of your activity', choices: [ { value: 'me', - label: this.$t('Nobody except me') + label: 'Nobody except me' }, { value: 'instance', - label: this.$t('Everyone on this instance') + label: 'Everyone on this instance' } ] } diff --git a/front/src/components/favorites/List.vue b/front/src/components/favorites/List.vue index 590d91592..d189f2b85 100644 --- a/front/src/components/favorites/List.vue +++ b/front/src/components/favorites/List.vue @@ -85,9 +85,9 @@ export default { orderingDirection: defaultOrdering.direction, ordering: defaultOrdering.field, orderingOptions: [ - ['title', this.$t('Track name')], - ['album__title', this.$t('Album name')], - ['artist__name', this.$t('Artist name')] + ['title', 'Track name'], + ['album__title', 'Album name'], + ['artist__name', 'Artist name'] ] } }, diff --git a/front/src/components/library/import/ArtistImport.vue b/front/src/components/library/import/ArtistImport.vue index 7486a65da..b24be6dc8 100644 --- a/front/src/components/library/import/ArtistImport.vue +++ b/front/src/components/library/import/ArtistImport.vue @@ -53,8 +53,14 @@ export default Vue.extend({ releaseImportData: [], releaseGroupsData: {}, releases: [], - releaseTypes: [this.$t('Album')], - availableReleaseTypes: [this.$t('Album'), this.$t('Live'), this.$t('Compilation'), this.$t('EP'), this.$t('Single'), this.$t('Other')] + releaseTypes: ['Album'], + availableReleaseTypes: [ + 'Album', + 'Live', + 'Compilation', + 'EP', + 'Single', + 'Other'] } }, created () { diff --git a/front/src/components/library/import/Main.vue b/front/src/components/library/import/Main.vue index cf261fad8..de17e2afa 100644 --- a/front/src/components/library/import/Main.vue +++ b/front/src/components/library/import/Main.vue @@ -38,13 +38,13 @@