diff --git a/ui/babel.config.json b/ui/babel.config.json
index d2f9ebf4..91cd094a 100644
--- a/ui/babel.config.json
+++ b/ui/babel.config.json
@@ -1,4 +1,15 @@
{
"presets": ["@babel/preset-react"],
- "plugins": ["styled-components", "graphql-tag"]
+ "plugins": [
+ "styled-components",
+ "graphql-tag",
+ [
+ "i18next-extract",
+ {
+ "locales": ["en", "da"],
+ "discardOldKeys": true,
+ "defaultValue": null
+ }
+ ]
+ ]
}
diff --git a/ui/extractedTranslations/da/translation.json b/ui/extractedTranslations/da/translation.json
new file mode 100644
index 00000000..936bb0cd
--- /dev/null
+++ b/ui/extractedTranslations/da/translation.json
@@ -0,0 +1,66 @@
+{
+ "albums_page": {
+ "title": "Album"
+ },
+ "loading": {
+ "paginate": {
+ "media": "Loader flere medier"
+ }
+ },
+ "login_page": {
+ "field": {
+ "password": "Adgangskode",
+ "submit": "Log ind",
+ "username": "Brugernavn"
+ },
+ "initial_setup": {
+ "field": {
+ "photo_path": "Billedesti"
+ },
+ "field-photo_path": {
+ "placeholder": "/sti/til/billeder"
+ },
+ "field-submit": "Opsæt Photoview",
+ "title": "Førstegangsopsætning"
+ },
+ "welcome": "Velkommen til Photoview"
+ },
+ "settings": {
+ "concurrent_workers": {
+ "description": "Det maksimale antal medier som må skannes samtidig",
+ "title": "Samtidige scanner-arbejdere"
+ },
+ "periodic_scanner": {
+ "checkbox_label": "Aktiver periodiske scanner",
+ "field": {
+ "description": "Hvor ofte scanneren bør udføre automatiske scanninger af alle brugere",
+ "label": "Periodiske scanningsintervaller"
+ },
+ "interval_unit": {
+ "days": "Dage",
+ "hour": "Timer",
+ "minutes": "Minutter",
+ "months": "Måneder",
+ "seconds": "Sekunder"
+ },
+ "title": "Periodisk scanner"
+ },
+ "scanner": {
+ "description": "Vil scanne alle brugere for nye eller opdaterede medier",
+ "scan_all_users": "Scan alle brugere",
+ "title": "Scanner"
+ }
+ },
+ "sidemenu": {
+ "albums": null,
+ "logout": "Log af",
+ "people": "Personer",
+ "photos": "Billeder",
+ "places": "Kort",
+ "settings": "Indstillinger"
+ },
+ "title": {
+ "loading_album": "Loader album",
+ "settings": "Indstillinger"
+ }
+}
diff --git a/ui/extractedTranslations/en/translation.json b/ui/extractedTranslations/en/translation.json
new file mode 100644
index 00000000..02cd8b10
--- /dev/null
+++ b/ui/extractedTranslations/en/translation.json
@@ -0,0 +1,66 @@
+{
+ "albums_page": {
+ "title": "Albums"
+ },
+ "loading": {
+ "paginate": {
+ "media": "Loading more media"
+ }
+ },
+ "login_page": {
+ "field": {
+ "password": "Password",
+ "submit": "Sign in",
+ "username": "Username"
+ },
+ "initial_setup": {
+ "field": {
+ "photo_path": "Photo path"
+ },
+ "field-photo_path": {
+ "placeholder": "/path/to/photos"
+ },
+ "field-submit": "Setup Photoview",
+ "title": "Initial Setup"
+ },
+ "welcome": "Welcome to Photoview"
+ },
+ "settings": {
+ "concurrent_workers": {
+ "description": "The maximum amount of scanner jobs that is allowed to run at once",
+ "title": "Scanner concurrent workers"
+ },
+ "periodic_scanner": {
+ "checkbox_label": "Enable periodic scanner",
+ "field": {
+ "description": "How often the scanner should perform automatic scans of all users",
+ "label": "Periodic scan interval"
+ },
+ "interval_unit": {
+ "days": "Days",
+ "hour": "Hour",
+ "minutes": "Minutes",
+ "months": "Months",
+ "seconds": "Seconds"
+ },
+ "title": "Periodic scanner"
+ },
+ "scanner": {
+ "description": "Will scan all users for new or updated media",
+ "scan_all_users": "Scan all users",
+ "title": "Scanner"
+ }
+ },
+ "sidemenu": {
+ "albums": "Albums",
+ "logout": "Log out",
+ "people": "People",
+ "photos": "Photos",
+ "places": "Places",
+ "settings": "Settings"
+ },
+ "title": {
+ "loading_album": "Loading album",
+ "settings": "Settings"
+ }
+}
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 37f2286d..67884c0e 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -18,6 +18,7 @@
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3",
"babel-plugin-graphql-tag": "^3.2.0",
+ "babel-plugin-i18next-extract": "^0.8.3",
"babel-plugin-styled-components": "^1.12.0",
"babel-plugin-transform-semantic-ui-react-imports": "^1.4.1",
"browser-sync": "^2.26.14",
@@ -3413,6 +3414,39 @@
"graphql-tag": "^2.10.1"
}
},
+ "node_modules/babel-plugin-i18next-extract": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-i18next-extract/-/babel-plugin-i18next-extract-0.8.3.tgz",
+ "integrity": "sha512-ZBhGjP2nLF3pGJO/X6s8DlyUo8zkuPQ09sGZK4XGqtJit/ccj8zocO5JI/F+oFZgKVH1tN8pAQT4fm0JWk2SIQ==",
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/types": "7.9.6",
+ "deepmerge": "^4.2.2",
+ "i18next": "^19.8.3",
+ "json-stable-stringify": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/babel-plugin-i18next-extract/node_modules/@babel/types": {
+ "version": "7.9.6",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+ "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.9.5",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "node_modules/babel-plugin-i18next-extract/node_modules/i18next": {
+ "version": "19.9.2",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-19.9.2.tgz",
+ "integrity": "sha512-0i6cuo6ER6usEOtKajUUDj92zlG+KArFia0857xxiEHAQcUwh/RtOQocui1LPJwunSYT574Pk64aNva1kwtxZg==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.0"
+ }
+ },
"node_modules/babel-plugin-istanbul": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz",
@@ -9161,6 +9195,14 @@
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
+ "node_modules/json-stable-stringify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
+ "dependencies": {
+ "jsonify": "~0.0.0"
+ }
+ },
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
@@ -9191,6 +9233,14 @@
"node": ">= 10.0.0"
}
},
+ "node_modules/jsonify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -16576,6 +16626,38 @@
"debug": "^4.1.1"
}
},
+ "babel-plugin-i18next-extract": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-i18next-extract/-/babel-plugin-i18next-extract-0.8.3.tgz",
+ "integrity": "sha512-ZBhGjP2nLF3pGJO/X6s8DlyUo8zkuPQ09sGZK4XGqtJit/ccj8zocO5JI/F+oFZgKVH1tN8pAQT4fm0JWk2SIQ==",
+ "requires": {
+ "@babel/core": "^7.12.3",
+ "@babel/types": "7.9.6",
+ "deepmerge": "^4.2.2",
+ "i18next": "^19.8.3",
+ "json-stable-stringify": "^1.0.1"
+ },
+ "dependencies": {
+ "@babel/types": {
+ "version": "7.9.6",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+ "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.9.5",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "i18next": {
+ "version": "19.9.2",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-19.9.2.tgz",
+ "integrity": "sha512-0i6cuo6ER6usEOtKajUUDj92zlG+KArFia0857xxiEHAQcUwh/RtOQocui1LPJwunSYT574Pk64aNva1kwtxZg==",
+ "requires": {
+ "@babel/runtime": "^7.12.0"
+ }
+ }
+ }
+ },
"babel-plugin-istanbul": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz",
@@ -21096,6 +21178,14 @@
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
+ "json-stable-stringify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
+ "requires": {
+ "jsonify": "~0.0.0"
+ }
+ },
"json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
@@ -21123,6 +21213,11 @@
}
}
},
+ "jsonify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
+ },
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
diff --git a/ui/package.json b/ui/package.json
index f61677e4..68d1e70d 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -18,6 +18,7 @@
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3",
"babel-plugin-graphql-tag": "^3.2.0",
+ "babel-plugin-i18next-extract": "^0.8.3",
"babel-plugin-styled-components": "^1.12.0",
"babel-plugin-transform-semantic-ui-react-imports": "^1.4.1",
"browser-sync": "^2.26.14",
diff --git a/ui/src/Layout.js b/ui/src/Layout.js
index d64dfb02..1a1799c3 100644
--- a/ui/src/Layout.js
+++ b/ui/src/Layout.js
@@ -108,31 +108,33 @@ export const SideMenu = () => {
Welcome to Photoview
-+ {t('login_page.welcome', 'Welcome to Photoview')} +
+