diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1a3bb81..708eb5a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
### Version 2.14.0
- added Farmer to list of available characters
+- added i18n support
---
diff --git a/package-lock.json b/package-lock.json
index 0e6afb9..bc5b5ad 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,11 +17,13 @@
"sass": "^1.30.0",
"sass-loader": "^8.0.2",
"vue": "^2.6.12",
+ "vue-i18n": "^8.24.4",
"vue-template-compiler": "^2.6.12",
"vuex": "^3.6.0",
"ws": "^7.4.6"
},
"devDependencies": {
+ "@kazupon/vue-i18n-loader": "^0.5.0",
"@vue/cli-plugin-eslint": "^4.5.9",
"@vue/eslint-config-prettier": "^6.0.0",
"eslint": "^6.7.2",
@@ -159,6 +161,35 @@
"webpack": "^4.0.0"
}
},
+ "node_modules/@kazupon/vue-i18n-loader": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@kazupon/vue-i18n-loader/-/vue-i18n-loader-0.5.0.tgz",
+ "integrity": "sha512-Tp2mXKemf9/RBhI9CW14JjR9oKjL2KH7tV6S0eKEjIBuQBAOFNuPJu3ouacmz9hgoXbNp+nusw3MVQmxZWFR9g==",
+ "deprecated": "WARNING: If you would like to use @kazupon/vue-i18n-loader that is released new features and bug fixes, you need to install @intlify/vue-i18n-loader.",
+ "dev": true,
+ "dependencies": {
+ "js-yaml": "^3.13.1",
+ "json5": "^2.1.1"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@kazupon/vue-i18n-loader/node_modules/json5": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
+ "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.5"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@mrmlnc/readdir-enhanced": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
@@ -10697,6 +10728,11 @@
"resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
"integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog=="
},
+ "node_modules/vue-i18n": {
+ "version": "8.24.4",
+ "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.24.4.tgz",
+ "integrity": "sha512-RZE94WUAGxEiBAANxQ0pptbRwDkNKNSXl3fnJslpFOxVMF6UkUtMDSuYGuW2blDrVgweIXVpethOVkYoNNT9xw=="
+ },
"node_modules/vue-loader": {
"version": "15.9.6",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.6.tgz",
@@ -12095,6 +12131,27 @@
"postcss": "^7.0.0"
}
},
+ "@kazupon/vue-i18n-loader": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@kazupon/vue-i18n-loader/-/vue-i18n-loader-0.5.0.tgz",
+ "integrity": "sha512-Tp2mXKemf9/RBhI9CW14JjR9oKjL2KH7tV6S0eKEjIBuQBAOFNuPJu3ouacmz9hgoXbNp+nusw3MVQmxZWFR9g==",
+ "dev": true,
+ "requires": {
+ "js-yaml": "^3.13.1",
+ "json5": "^2.1.1"
+ },
+ "dependencies": {
+ "json5": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
+ "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ }
+ }
+ },
"@mrmlnc/readdir-enhanced": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
@@ -20511,6 +20568,11 @@
"resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
"integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog=="
},
+ "vue-i18n": {
+ "version": "8.24.4",
+ "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.24.4.tgz",
+ "integrity": "sha512-RZE94WUAGxEiBAANxQ0pptbRwDkNKNSXl3fnJslpFOxVMF6UkUtMDSuYGuW2blDrVgweIXVpethOVkYoNNT9xw=="
+ },
"vue-loader": {
"version": "15.9.6",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.6.tgz",
diff --git a/package.json b/package.json
index 17260d4..40c0593 100644
--- a/package.json
+++ b/package.json
@@ -20,11 +20,13 @@
"sass": "^1.30.0",
"sass-loader": "^8.0.2",
"vue": "^2.6.12",
+ "vue-i18n": "^8.24.4",
"vue-template-compiler": "^2.6.12",
"vuex": "^3.6.0",
"ws": "^7.4.6"
},
"devDependencies": {
+ "@kazupon/vue-i18n-loader": "^0.5.0",
"@vue/cli-plugin-eslint": "^4.5.9",
"@vue/eslint-config-prettier": "^6.0.0",
"eslint": "^6.7.2",
diff --git a/src/assets/translations/en.json b/src/assets/translations/en.json
new file mode 100644
index 0000000..e0e5026
--- /dev/null
+++ b/src/assets/translations/en.json
@@ -0,0 +1,168 @@
+{
+ "menu": {
+ "grimoire": "Grimoire",
+ "zoom": "Zoom",
+ "other-players-in-session": "other players in this session",
+ "show-background-image": "Show background image",
+ "background-image": "Background image",
+ "show-custom-image": "Show custom image",
+ "night-order": "Night order",
+ "disable-animations": "Disable animations",
+ "mute-sounds": "Mute sounds",
+ "playing": "Playing",
+ "hosting": "Hosting",
+ "switch-night": "Switch to night",
+ "switch-day": "Switch to day",
+ "show": "Show",
+ "hide": "Hide",
+ "live-session": "Live Session",
+ "delay-to": "Delay to ",
+ "vote-history": "Vote history",
+ "leave-session": "Leave Session",
+ "players": "Players",
+ "add": "Add",
+ "randomize": "Randomize",
+ "remove-all": "Remove all",
+ "characters": "Characters",
+ "select-edition": "Select Edition",
+ "choose-assign": "Choose & Assign",
+ "add-fabled": "Add Fabled",
+ "help": "Help",
+ "reference-sheet": "Reference Sheet",
+ "night-order-sheet": "Night Order Sheet",
+ "game-state-json": "Game State JSON",
+ "join-discord": "Join Discord",
+ "source-code": "Source code",
+ "host": "Host (Storyteller)",
+ "join": "Join (Player)",
+ "copy-player-link": "Copy player link",
+ "send-characters": "Send characters",
+ "player-name": "Player name",
+ "enter-background": "Enter custom background URL",
+ "create-session": "Enter a channel number / name for your session",
+ "distribute-roles": "Do you want to distribute assigned characters to all SEATED players?",
+ "custom-images-warn": "Are you sure you want to allow custom images? A malicious script file author might track your IP address this way.",
+ "join-session": "Enter the channel number / name of the session you want to join",
+ "leave-warn": "Are you sure you want to leave the active live game?",
+ "randomize-warn": "Are you sure you want to randomize seatings?",
+ "remove-players-warn": "Are you sure you want to remove all players?",
+ "remove-roles-warn": "Are you sure you want to remove all player roles?"
+ },
+ "intro": {
+ "welcome": "Welcome to the (unofficial) {grimoire} for Blood on the Clocktower ! Please add more players through the {menu} on the top right or by pressing {a-key}. You can also join a game session by pressing {j-key}.",
+ "townsquare-grimoire": "Virtual Town Square and Grimoire",
+ "menu": "Menu",
+ "project-notice": "This project is free and open source and can be found on {github}. It is not affiliated with The Pandemonium Institute. \"Blood on the Clocktower\" is a trademark of Steven Medway and The Pandemonium Institute."
+ },
+ "player": {
+ "change-pronouns": "Change Pronouns",
+ "rename": "Rename",
+ "move-player": "Move player",
+ "swap-seats": "Swap seats",
+ "remove": "Remove",
+ "empty-seat": "Empty seat",
+ "nomination": "Nomination",
+ "claim-seat": "Claim seat",
+ "vacate-seat": "Vacate seat",
+ "seat-occupied": "Seat occupied",
+ "player-name": "Player name"
+ },
+ "town-info": {
+ "add-more": "Please add more players!",
+ "night-phase": "Night phase"
+ },
+ "townsquare": {
+ "other-characters": "Other characters",
+ "demon-bluffs": "Demon bluffs",
+ "fabled": "Fabled"
+ },
+ "vote": {
+ "nominated": "nominated",
+ "vote": "vote",
+ "in-favor": "in favor",
+ "majority-is": "majority is",
+ "time-per-player": "Time per player",
+ "countdown": "Countdown",
+ "restart": "Restart",
+ "start": "Start",
+ "pause": "Pause",
+ "resume": "Resume",
+ "reset": "Reset",
+ "close": "Close",
+ "mark-execution": "Mark for execution",
+ "clear-mark": "Clear mark",
+ "seconds-between-votes": "seconds between votes",
+ "hand-down": "Hand DOWN",
+ "hand-up": "Hand UP",
+ "claim-seat": "Please claim a seat to vote"
+ },
+ "edition-modal": {
+ "select-edition": "Select an edition:",
+ "custom-script": "Custom Script / Characters",
+ "load-script-title": "Load custom script / characters",
+ "load-script-help": "To play with a custom script, you need to select the characters you want to play with in the official {link} and then upload the generated \"custom-list.json\" either directly here or provide a URL to such a hosted JSON file.",
+ "script-tool": "Script Tool",
+ "custom-characters-notice": "To play with custom characters, please read {documentation} on how to write a custom character definition file.",
+ "documentation": "the documentation",
+ "trusted-sources": "Only load custom JSON files from sources that you trust!",
+ "popular-scripts": "Some popular custom scripts:",
+ "upload-json": "Upload JSON",
+ "enter-url": "Enter URL",
+ "back": "Back"
+ },
+ "fabled-modal": {
+ "choose-fabled": "Choose a fabled character to add to the game"
+ },
+ "game-state-modal": {
+ "current-game-state": "Current Game State",
+ "copy-json": "Copy JSON",
+ "load-state": "Load State"
+ },
+ "night-order-modal": {
+ "show-reference": "Show Character Reference",
+ "night-order": "Night Order",
+ "first-night": "First Night",
+ "other-nights": "Other Nights",
+ "minion-info": "Minion info",
+ "minion-reminder": "• If more than one Minion, they all make eye contact with each other. • Show the “This is the Demon” card. Point to the Demon.",
+ "demon-info": "Demon info & bluffs",
+ "demon-reminder": "• Show the “These are your minions” card. Point to each Minion. • Show the “These characters are not in play” card. Show 3 character tokens of good characters not in play."
+ },
+ "reference-modal": {
+ "show-night-order": "Show Night Order",
+ "character-reference": "Character Reference",
+ "jinxed": "Jinxed",
+ "townsfolk": "Townsfolk",
+ "outsider": "Outsider",
+ "minion": "Minion",
+ "demon": "Demon"
+ },
+ "reminder-modal": {
+ "reminder-token": "Choose a reminder token"
+ },
+ "role-modal": {
+ "choose-character": "Choose a new character for {player}",
+ "bluffing": "bluffing",
+ "edition-roles": "Edition Roles",
+ "other-travelers": "Other Travelers"
+ },
+ "roles-modal": {
+ "select-roles": "Select the characters for {nonTravelers} players:",
+ "warning-incorrect-setup": "Warning: there are characters selected that modify the game setup! The randomizer does not account for these characters.",
+ "allow-duplicate": "Allow duplicate characters",
+ "assign-randomly": "Assign {roles} characters randomly",
+ "shuffle": "Shuffle characters"
+ },
+ "vote-history-modal": {
+ "vote-history": "Vote history",
+ "accessible-players": "Accessible to players",
+ "clear": "Clear for everyone",
+ "time": "Time",
+ "nominator": "Nominator",
+ "nominee": "Nominee",
+ "type": "Type",
+ "votes": "Votes",
+ "majority": "Majority",
+ "voters": "Voters"
+ }
+}
diff --git a/src/components/Intro.vue b/src/components/Intro.vue
index 39e7e35..e3874ec 100644
--- a/src/components/Intro.vue
+++ b/src/components/Intro.vue
@@ -1,19 +1,31 @@
- Welcome to the (unofficial)
- Virtual Town Square and Grimoire for Blood on the Clocktower! Please
- add more players through the
-
- on the top right or by pressing [A]. You can also join a game session
- by pressing [J].
+
- Other characters
- Demon bluffs
+
+ {{ $t("townsquare.other-characters") }}
+
+
+ {{ $t("townsquare.demon-bluffs") }}
+
@@ -48,7 +52,9 @@
- Fabled
+
+ {{ $t("townsquare.fabled") }}
+
diff --git a/src/components/Vote.vue b/src/components/Vote.vue
index c37df21..6c67b51 100644
--- a/src/components/Vote.vue
+++ b/src/components/Vote.vue
@@ -6,22 +6,24 @@
Time | -Nominator | -Nominee | -Type | -Votes | -Majority | +{{ $t("vote-history-modal.time") }} | +{{ $t("vote-history-modal.nominator") }} | +{{ $t("vote-history-modal.nominee") }} | +{{ $t("vote-history-modal.type") }} | +{{ $t("vote-history-modal.votes") }} | +{{ $t("vote-history-modal.majority") }} |
|