Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multilingual support #246

Merged
merged 39 commits into from
Feb 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
861139e
First draft for i18n support #123
m-mohr Dec 21, 2022
11d09ac
Async loading for languages, translate bootstrap and sidebar
m-mohr Dec 21, 2022
d3b41f6
Translate zoom control
m-mohr Dec 22, 2022
be35415
Further translations
m-mohr Dec 22, 2022
c66a2fe
Persist language in URL, further translations, bugfixes, separate com…
m-mohr Dec 22, 2022
f2b5cdd
More translations...
m-mohr Jan 3, 2023
8073680
Merge remote-tracking branch 'origin/dev' into i18n
m-mohr Jan 4, 2023
46664cc
Translations for errors, search and filtering, bug fixes
m-mohr Jan 4, 2023
f780d04
Localize datepicker
m-mohr Jan 4, 2023
4e4d4e2
Fix lint issues
m-mohr Jan 4, 2023
54d1f26
Adding Frensh language files (#248)
m-mohr Jan 9, 2023
4502659
Implement language switching for static catalogs, send Accept-Header,…
m-mohr Jan 10, 2023
c42b74b
Fix language switching based on Browser settings
m-mohr Jan 11, 2023
bafc0fa
Started translating metadata
m-mohr Jan 11, 2023
c6d5e9f
Minor improvements
m-mohr Jan 13, 2023
26151e7
Allow selecting "incomplete" languages
m-mohr Jan 13, 2023
f643cfe
Improve table rendering for languages
m-mohr Jan 13, 2023
e1b4dec
Merge branch 'dev' into i18n
m-mohr Jan 13, 2023
e94c484
Add locales from stac-fields
m-mohr Jan 16, 2023
5bab70d
Added more French language labels
m-mohr Jan 16, 2023
7c99fc2
German translations etc.
m-mohr Jan 16, 2023
d03bdb8
Initialize uiLanguage correctly
m-mohr Jan 19, 2023
9b6a1eb
Add media type based texts
m-mohr Jan 19, 2023
1e853e9
Merge branch 'dev' into i18n
m-mohr Jan 19, 2023
6947fd5
Further German translations
m-mohr Jan 19, 2023
9863784
Merge branch 'dev' into i18n
m-mohr Jan 19, 2023
785ee9a
Additional translations
m-mohr Jan 19, 2023
6fbe315
Merge branch 'dev' into i18n
m-mohr Jan 27, 2023
35aeee9
Merge branch 'dev' into i18n
m-mohr Feb 2, 2023
47caddb
Implement basic API language support
m-mohr Feb 2, 2023
cd68ec1
Further translations
m-mohr Feb 2, 2023
1d79b75
Merge branch 'dev' into i18n
m-mohr Feb 6, 2023
50d017c
Fixed typo
m-mohr Feb 7, 2023
03e8638
initial French translation of STAC fields
jfbourgon Feb 6, 2023
77b6129
Add missing translation and clean-up
m-mohr Feb 7, 2023
9eaf664
Add missing translations
m-mohr Feb 7, 2023
a085d0e
Reusable phrases
m-mohr Feb 7, 2023
81c1853
Merge branch 'i18n' into i18n-import
m-mohr Feb 7, 2023
1c740a0
Merge branch 'dev' into i18n
m-mohr Feb 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,32 @@ Must be set to `true` if a `catalogUrl` is not given as otherwise you won't be a

You can list additional domains (e.g. `example.com`) that private data is sent to, e.g. authentication data.

### detectLocaleFromBrowser

If set to `true`, tries to detect the preferred language of the user from the Browser.
Otherwise, defaults to the language set for `locale`.

### locale

The default language to use for STAC Browser, defaults to `en` (English).
The language given here must be present in `supportedLocales`.

### fallbackLocale

The language to use if individual phrases are not available in the default language, defaults to `en` (English).
The language given here must be present in `supportedLocales`.

### supportedLocales

A list of languages to show in the STAC Browser UI.
The languages given here must have a corresponding JS and JSON file in the `src/locales` folder,
e.g. provide `en` (English) for the files in `src/locales/en`.

In CLI, please provide the languages separated by a space, e.g. `--supportedLocales en de fr it`

Please note that only left-to-right languages have been tested.
I'd need help to test support for right-to-left languages.

### stacLint

***experimental***
Expand Down Expand Up @@ -230,6 +256,7 @@ There are four options you can set in the `authConfig` object:
* `key` (string): The query string parameter name or the HTTP header name respecively.
* `formatter` (function|null): You can optionally specify a formatter for the query string value or HTTP header value respectively. If not given, the token is provided as provided by the user.
* `description` (string|null): Optionally a description that is shown to the user. This should explain how the token can be obtained for example. CommonMark is allowed.
**Note:** You can leave the description empty in the config file and instead provide a localized string with the key `authConfig` -> `description` in the file for custom phrases (`src/locales/custom.js`).

Please note that this option can only be provided through a config file and is not available via CLI.

Expand Down
10 changes: 10 additions & 0 deletions config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ module.exports = {
catalogTitle: "STAC Browser",
allowExternalAccess: true, // Must be true if catalogUrl is not given
allowedDomains: [],
detectLocaleFromBrowser: true,
locale: "en",
fallbackLocale: "en",
supportedLocales: [
"en",
"en-US",
"de",
"fr-CA",
"fr-FR"
],
useTileLayerAsFallback: true,
tileSourceTemplate: null,
displayGeoTiffByDefault: false,
Expand Down
73 changes: 73 additions & 0 deletions helpers/fields_locales.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const Fields = require('@radiantearth/stac-fields/fields-normalized.json');
const HardCodedFields = require("./fields_locales.json");
const fs = require('fs');

const translatable = ["label", "explain", "unit"];
const iterable = ["items", "properties"];
const dest_file = "src/locales/en/fields.json";

function ignore(text, path, otherPath) {
if (path.endsWith(".unit")) {
return true;
}
if (path.includes(".id.") || path.includes(".name.") || path.includes(".title.") || path.includes(".description.")) {
return true;
}
if (path.includes(".href") || path.includes(".roles.")) {
return true;
}
if (path.includes(".average.") || path.includes(".minimum.") || path.includes(".maximum.") || path.includes(".stddev.")) {
return true;
}
if (path.includes("cube:") && otherPath.includes("cube:")) {
return true;
}
if (path.includes("links.type.") && otherPath.includes("assets.type.")) {
return true;
}
if (path.includes(".mgrs.")) {
return true;
}
return false;
}

function addText(locales, text, path) {
if (locales[text] && !ignore(text, path, locales[text])) {
console.warn(`Potential conflict between '${path}' and '${locales[text]}'`);
}
locales[text] = path;
}

function findTexts(locales, fields, path) {
for(let name in fields) {
let field = fields[name];
if (field.alias) {
continue;
}

translatable.forEach(key => field[key] && addText(locales, field[key], `${path}.${name}.${key}`));
iterable.forEach(key => field[key] && findTexts(locales, field[key], `${path}.${name}.${key}`));
if (field.mapping) {
Object.entries(field.mapping).forEach(([key, text]) => addText(locales, text, `${path}.${name}.mapping.${key}`));
}
}
}

function writeToFile(file, locales) {
const data = {};
Object.keys(locales).sort().forEach(key => data[key] = key);
const json = JSON.stringify(data, null, 2);
fs.writeFileSync(file, json);
}

function generateLocales() {
const locales = {};
HardCodedFields.forEach(text => addText(locales, text, "hardcoded"));
const types = ["assets", "extensions", "links", "metadata"];
types.forEach(type => findTexts(locales, Fields[type], type));
writeToFile(dest_file, locales);
}

console.log(`Generating fields locale file`);
generateLocales();
console.log(`Saved fields locale file to ${dest_file}`);
87 changes: 87 additions & 0 deletions helpers/fields_locales.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
[
"n/a",
"none",

"Hashing algorithm:",

"Until {0}",
"{0} until present",

"8-bit integer",
"16-bit integer",
"32-bit integer",
"64-bit integer",
"unsigned 8-bit integer",
"unsigned 16-bit integer",
"unsigned 32-bit integer",
"unsigned 64-bit integer",
"16-bit float",
"32-bit float",
"64-bit float",
"16-bit complex integer",
"32-bit complex integer",
"32-bit complex float",
"64-bit complex float",
"non-standard",

"MGRS",
"Military Grid Reference System",
"UTM Zone",
"Latitude Band",
"Square Identifier",
"Easting",
"Northing",
"MODIS Sinusoidal Tile Grid",
"Horizontal",
"Vertical",
"WRS-1",
"Worldwide Reference System 1",
"WRS-2",
"Worldwide Reference System 2",
"Path",
"Row",
"DOQ",
"Digital Orthophoto Quadrangle",
"Quadrangle",
"DOQQ",
"Digital Orthophoto Quarter Quadrangle",
"North",
"East",
"South",
"West",
"Quarter",
"Maxar ARD Tile Grid",
"Quadkey",
"EASE-DGGS",
"Level",
"Level 0 row cell",
"Level 0 column cell",
"Fraction of level {i} row cell",
"Fraction of level {i} column cell",

"Cloud-Optimized GeoTIFF image",
"GeoTIFF image",
"TIFF image",
"JPEG 2000 image",
"PNG image",
"GIF image",
"JPEG image",
"WebP image",
"Bitmap",
"Bitmap image",
"SVG vector image",
"Comma-separated values (CSV)",
"Newline Delimited JSON",
"HTML (Website)",
"Text",
"Text document",
"Markdown document",
"PDF document",
"ZIP archive",
"GZIP archive",
"Meta Raster Format",
"Binary",
"Binary file",
"Cloud-Optimized Point Cloud (LASzip)",
"Font"
]
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"scripts": {
"start": "vue-cli-service serve",
"build": "vue-cli-service build --report",
"lint": "vue-cli-service lint"
"lint": "vue-cli-service lint",
"i18n:report": "vue-cli-service i18n:report --src \"./src/**/*.?(js|vue)\" --locales \"./src/locales/**/*.(js|json)\"",
"i18n:fields": "node helpers/fields_locales.js"
},
"bugs": {
"url": "https://github.com/radiantearth/stac-browser/issues"
Expand All @@ -30,6 +32,7 @@
"license": "ISC",
"dependencies": {
"@apidevtools/json-schema-ref-parser": "^9.0.9",
"@musement/iso-duration": "^1.0.0",
"@radiantearth/stac-fields": "1.0.0-beta.25",
"@radiantearth/stac-migrate": "~1.2.0",
"axios": "^1.2.0",
Expand All @@ -38,12 +41,14 @@
"commonmark": "^0.29.3",
"core-js": "^3.6.5",
"leaflet": "^1.8.0",
"locale-id": "^1.1.2",
"node-polyfill-webpack-plugin": "^2.0.0",
"remove-markdown": "^0.5.0",
"stac-layer": "^0.15.0",
"urijs": "^1.19.11",
"v-clipboard": "^2.2.3",
"vue": "^2.6.12",
"vue-i18n": "^8.28.2",
"vue-multiselect": "^2.1.6",
"vue-read-more-smooth": "^0.1.8",
"vue-router": "^3.2.0",
Expand All @@ -64,6 +69,7 @@
"eslint-plugin-vue": "^8.7.1",
"sass": "^1.26.5",
"sass-loader": "^13.2.0",
"vue-cli-plugin-i18n": "~2.3.1",
"vue-template-compiler": "^2.6.12"
},
"browserslist": [
Expand Down
Loading