## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [x] I understand that submitting code with bugs that could have been
caught through manual testing blocks releases and new features for all
contributors

This is commit pack
This PR refactors and improves the language selection experience:
• Centralizes all language-related logic in LangSelector.ts &
LanguageModal.ts
	•	Redesigns the language selection UI for better UX across devices
	•	Adds new translations and supports more languages
Changes .w.
• Language selection is now handled entirely inside LangSelector.ts &
LanguageModal.ts
	•	Prevents background scrolling when open
	•	Highlights the current language at the top
	•	Always shows English second
	•	Shows browser language third (if different from current)
	•	All other languages are sorted alphabetically by English name
	•	Debug option is shown at the end when pressing D
	•	The language list is scrollable when it exceeds screen height
	
Supported Languages
["en", "ja", "fr", "bg", "nl", "ru", "ua", "de"]

Added Translation Keys
```
"lang": {
  "en": "English",
  "native": "English",
  "svg": "xx"
},
"map": {
  "map": "Map"
},
"game_starting_modal": {
  "title": "Game is Starting...",
  "desc": "Preparing for the lobby to start. Please wait."
},
"difficulty": {
  "difficulty": "Difficulty"
}
```

## Please put your Discord username so you can be contacted if a bug or
regression is found:
MLS Representative
- aotumuri 

Translation collaborator
- Nikola123 (He was a very big help from setting up the translation site
to adding the json. Thank you so much!)
I don't have permission from my collaborators to display their names
here, so I'll put the discord link here

https://discord.com/channels/1284581928254701718/1352553113612980224/1352553113612980224
- tryout33

Collaborators from other servers.
- CCC Group (This is not Culture Convenience Club. Think of it like a
server where developers of various games are playing.)
- People who fixed the UI and found bugs.
meow02952 (discord id) <- This person also gave me a code suggestion.
Thanks!
moon_spear (discord id)
ww_what_ww (discord id)
Azuna (he doesn't have discord account)
- People who corrected translations, etc.
_kyoyume_ (discord id)
_ultrasuper_ (discord id)
grueg (he doesn't have discord account)

# If I forgot to include your name, or if you’d like your name to be
added, please let me know via Gmail or Discord.

---------

Co-authored-by: Duwibi <86431918+Duwibi@users.noreply.github.com>
This commit is contained in:
Aotumuri
2025-04-02 20:37:36 -07:00
committed by GitHub
co-authored by Duwibi
parent f09801fe3e
commit 607e5b5ff0
23 changed files with 1574 additions and 459 deletions
+4 -4
View File
@@ -98,7 +98,7 @@
"mrmime": "^2.0.0", "mrmime": "^2.0.0",
"postcss": "^8.5.1", "postcss": "^8.5.1",
"postcss-loader": "^8.1.1", "postcss-loader": "^8.1.1",
"prettier": "^3.5.0", "prettier": "^3.5.3",
"prettier-plugin-organize-imports": "^4.1.0", "prettier-plugin-organize-imports": "^4.1.0",
"raw-loader": "^4.0.2", "raw-loader": "^4.0.2",
"sinon": "^18.0.0", "sinon": "^18.0.0",
@@ -16171,9 +16171,9 @@
} }
}, },
"node_modules/prettier": { "node_modules/prettier": {
"version": "3.5.0", "version": "3.5.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.0.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
"integrity": "sha512-quyMrVt6svPS7CjQ9gKb3GLEX/rl3BCL2oa/QkNcXv4YNVBC9olt3s+H7ukto06q7B1Qz46PbrKLO34PR6vXcA==", "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"bin": { "bin": {
+1 -1
View File
@@ -59,7 +59,7 @@
"mrmime": "^2.0.0", "mrmime": "^2.0.0",
"postcss": "^8.5.1", "postcss": "^8.5.1",
"postcss-loader": "^8.1.1", "postcss-loader": "^8.1.1",
"prettier": "^3.5.0", "prettier": "^3.5.3",
"prettier-plugin-organize-imports": "^4.1.0", "prettier-plugin-organize-imports": "^4.1.0",
"raw-loader": "^4.0.2", "raw-loader": "^4.0.2",
"sinon": "^18.0.0", "sinon": "^18.0.0",
+50 -35
View File
@@ -1,37 +1,37 @@
{ {
"main": { "main": {
"join_discord": "Влизане в Дискорд!", "join_discord": "Влез в Дискорд!",
"create_lobby": "Създаване на Лоби", "create_lobby": "Създай частна игра",
"join_lobby": "Влизане в Лоби", "join_lobby": "Присъединяване към частна игра",
"single_player": "Самостоятелна Игра", "single_player": "Самостоятелна игра",
"instructions": "Инструкции", "instructions": "Инструкции",
"how_to_play": "Как се играе", "how_to_play": "Как се играе",
"wiki": "Уики" "wiki": "Уики"
}, },
"help_modal": { "help_modal": {
"hotkeys": "Бълзи клавиши", "hotkeys": "Бързи клавиши",
"table_key": "Бутон", "table_key": "Бутон",
"table_action": "Действие", "table_action": "Действие",
"action_alt_view": "Алтернативен изглед (терен/държави)", "action_alt_view": "Алтернативен изглед (терен/държави)",
"action_attack_altclick": "Атака (когато левият бутон е зададен за отваряне на меню)", "action_attack_altclick": "Атака (когато левият бутон е зададен за отваряне на меню)",
"action_build": "Отваряне на меню за строене", "action_build": "Отваряне на меню за строене",
"action_center": "Центриране на камера върху играч", "action_center": "Центриране на камерата върху играч",
"action_zoom": "Променяне на мащаба навън/навътре", "action_zoom": "Приближаване/Отдалечаване на камерата",
"action_move_camera": "Преместване на камера", "action_move_camera": "Преместване на камера",
"action_ratio_change": "Намаляване/Увеличаване на съотношение на атака", "action_ratio_change": "Намаляване/Увеличаване на съотношение на атака",
"action_reset_gfx": "Анулиране на графики", "action_reset_gfx": "Рестартиране на графики",
"ui_section": "Потребителски интерфейс на играта", "ui_section": "Потребителски интерфейс на играта",
"ui_leaderboard": "Класация", "ui_leaderboard": "Класация",
"ui_leaderboard_desc": "Показва топ играчите на играта и техните имена, % притежавана земя и злато.", "ui_leaderboard_desc": "Показва най-напредналите играчи в играта и техните имена, % притежавана земя и злато.",
"ui_control": "Контролен панел", "ui_control": "Контролен панел",
"ui_control_desc": "Контролният панел съдържа следните елементи:", "ui_control_desc": "Контролният панел съдържа следните елементи:",
"ui_pop": "Поп - Количеството хора, които имате, максималната Ви популация и скоростта, с която тя се увеличава.", "ui_pop": "Pop (Популация) - Количеството популация, която притежавате, максималната Ви популация и скоростта, с която тя се увеличава.",
"ui_gold": "Количеството злато, което имате и скоростта, с която го получавате.", "ui_gold": "Gold (Злато) - Количеството злато, което притежавате и скоростта, с която го получавате.",
"ui_troops_workers": "Войници и Работници - Количеството разпределени войници и работници. Войниците се използват за атакуване или защитаване срещу атаки. Работниците се използват за генериране на злато. Можете да коригирате количеството войници и работници, използвайки плъзгача.", "ui_troops_workers": "Войници и Работници - Количеството разпределени войници и работници. Войниците се използват за атакуване или защитаване срещу атаки. Работниците се използват за генериране на злато. Можете да коригирате количеството войници и работници, използвайки плъзгача.",
"ui_attack_ratio": "Съотношение на атака - Количеството войници, които ще се използват при атака. Можете да коригирате съотношението на атака, използвайки плъзгача.", "ui_attack_ratio": "Съотношение на атака - Количеството войници, които ще се използват при атака. Можете да коригирате съотношението на атака, използвайки плъзгача.",
"ui_options": "Опции", "ui_options": "Опции",
"ui_options_desc": "Следните елементи могат да бъдат намерени вътре:", "ui_options_desc": "Следните елементи могат да бъдат намерени вътре:",
"option_pause": "Поставяне на пауза/Премахване на пауза на играта - Налични само в самостоятелна игра.", "option_pause": "Поставяне/Премахване на пауза на играта - Налични само в самостоятелна игра.",
"option_timer": "Таймер - Изминалото време от началото на играта.", "option_timer": "Таймер - Изминалото време от началото на играта.",
"option_exit": "Бутон за изход.", "option_exit": "Бутон за изход.",
"option_settings": "Настройки - Отваряне на менюто за настройки. Вътре можете да превключите Алтернативния изглед, Тъмния режим, Емоджитата и действие при щракване на левия бутон.", "option_settings": "Настройки - Отваряне на менюто за настройки. Вътре можете да превключите Алтернативния изглед, Тъмния режим, Емоджитата и действие при щракване на левия бутон.",
@@ -39,10 +39,10 @@
"radial_desc": "Натискане на десния бутон (или докосване при мобилни устройства) отваря радиалното меню. Оттам можете да:", "radial_desc": "Натискане на десния бутон (или докосване при мобилни устройства) отваря радиалното меню. Оттам можете да:",
"radial_build": "Отворите менюто за строене.", "radial_build": "Отворите менюто за строене.",
"radial_info": "Отворите информационното меню.", "radial_info": "Отворите информационното меню.",
"radial_boat": "Изпратите лодка да атакува на посочената локация (налично само, ако имате достъп до вода).", "radial_boat": "Изпратите лодка да атакува посочената локация (налично само, ако имате достъп до вода).",
"radial_close": "Затворите менюто.", "radial_close": "Затворите менюто.",
"info_title": "Информационно меню", "info_title": "Информационно меню",
"info_enemy_desc": "Съдържа информация като името на селектирания играч, злато, войници, и дали играчът е предател. Предател е играч, който е предал и атакувал друг играч, който е бил в съюзничество с него. Иконките отдолу представляват следните взаимодействия:", "info_enemy_desc": "Съдържа информация като името на избрания играч, злато, войници, и дали играчът е предател. Предател е играч, който е предал и атакувал друг играч, който е бил в съюзничество с него. Иконките отдолу представляват следните взаимодействия:",
"info_target": "Поставяне на целева маркировка върху играча, маркирайки го за всички съюзници, използвано за координиране на атаки.", "info_target": "Поставяне на целева маркировка върху играча, маркирайки го за всички съюзници, използвано за координиране на атаки.",
"info_alliance": "Изпращане на заявка за съюзничество до играча. Съюзници могат да споделят ресурси и войски, но не могат да се атакуват взаимно.", "info_alliance": "Изпращане на заявка за съюзничество до играча. Съюзници могат да споделят ресурси и войски, но не могат да се атакуват взаимно.",
"info_emoji": "Изпращане на емоджи до играча.", "info_emoji": "Изпращане на емоджи до играча.",
@@ -61,7 +61,7 @@
"build_port": "Пристанище", "build_port": "Пристанище",
"build_port_desc": "Автоматично изпраща търговски кораби между пристанищата на вашата страна и други държави (освен ако сте щракнали върху \"спиране на търговията\" върху тях или те са щракнали върху \"спиране на търговията с вас\"), давайки злато и на двете страни. Позволява изграждането на бойни кораби. Може да се строи само близо до вода.", "build_port_desc": "Автоматично изпраща търговски кораби между пристанищата на вашата страна и други държави (освен ако сте щракнали върху \"спиране на търговията\" върху тях или те са щракнали върху \"спиране на търговията с вас\"), давайки злато и на двете страни. Позволява изграждането на бойни кораби. Може да се строи само близо до вода.",
"build_warship": "Боен кораб", "build_warship": "Боен кораб",
"build_warship_desc": "Патрулира в даден район, превземайки търговски кораби и унищожавайки вражески военни кораби и лодки. Поражда се от най-близкото пристанище и патрулира района, в който първо сте щракнали, за да го построите.", "build_warship_desc": "Патрулира в даден район, като превзема търговски кораби и унищожава вражески военни кораби и лодки. Създава се от най-близкото пристанище и патрулира района, в който първо сте щракнали, за да го построите.",
"build_silo": "Ракетен силоз", "build_silo": "Ракетен силоз",
"build_silo_desc": "Позволява изстрелване на ракети.", "build_silo_desc": "Позволява изстрелване на ракети.",
"build_sam": "Противоракетна установка земя-въздух SAM", "build_sam": "Противоракетна установка земя-въздух SAM",
@@ -81,16 +81,14 @@
}, },
"single_modal": { "single_modal": {
"title": "Самостоятелна Игра", "title": "Самостоятелна Игра",
"map": "Карта",
"difficulty": "Трудност",
"allow_alliances": "Позволяване на съюзничества", "allow_alliances": "Позволяване на съюзничества",
"options_title": "Опции", "options_title": "Опции",
"bots": "Ботове: ", "bots": "Ботове: ",
"bots_disabled": "Изключено", "bots_disabled": "Изключено",
"disable_nations": "Изключване на нации", "disable_nations": "Изключване на нации",
"instant_build": "Незабавно изграждане", "instant_build": "Незабавно построяване",
"infinite_gold": "Безкрайно злато", "infinite_gold": "Безкрайно злато",
"infinite_troops": "Безкрайни войници", "infinite_troops": "Безкрайна популация",
"disable_nukes": "Изключване на ядрени оръжия", "disable_nukes": "Изключване на ядрени оръжия",
"start": "Започване на игра" "start": "Започване на игра"
}, },
@@ -110,51 +108,68 @@
"australia": "Австралия", "australia": "Австралия",
"random": "Произволна", "random": "Произволна",
"iceland": "Исландия", "iceland": "Исландия",
"pangaea": "Пангея" "pangaea": "Пангея",
"map": "Карта",
"betweentwoseas": "Между Две Морета",
"japanandneighbors": "Япония и съседи"
}, },
"private_lobby": { "private_lobby": {
"title": "Влизане в частно лоби", "title": "Присъединяване към частна игра",
"enter_id": "Въведете ID на лобито", "enter_id": "Въведете ID на частната игра",
"player": "Играч", "player": "Играч",
"players": "Играчи", "players": "Играчи",
"join_lobby": "Влизане в лоби", "join_lobby": "Присъединяване към частна игра",
"checking": "Проверяване на лоби...", "checking": "Проверяване на частна игра...",
"not_found": "Не е намерено лобито. Моля, проверете ID-то и опитайте отново.", "not_found": "Не е намерена частната игра. Моля, проверете ID-то и опитайте отново.",
"error": "Възникна грешка. Моля, опитайте отново.", "error": "Възникна грешка. Моля, опитайте отново.",
"joined_waiting": "Влизането е успешно! Чакане за започване на играта..." "joined_waiting": "Присъединяването е успешно! Чакане за започване на играта..."
}, },
"public_lobby": { "public_lobby": {
"join": "Влизане в следващата игра", "join": "Присъединяване към следващата игра",
"waiting": "чакащи играчи" "waiting": "чакащи играчи"
}, },
"username": { "username": {
"enter_username": "Въведете потребителското си име", "enter_username": "Въведете потребителско име",
"not_string": "Потребителското име трябва да е символен низ.", "not_string": "Потребителското име трябва да е символен низ.",
"too_short": "Потребителското име трябва да е дълго поне {min} символа.", "too_short": "Потребителското име трябва да е дълго поне {min} символа.",
"too_long": "Потребителското име не трябва да надвишава {max} символа.", "too_long": "Потребителското име не трябва да надвишава {max} символа.",
"invalid_chars": "Потребителското име може да съдържа само букви, цифри, интервали, долни черти и [квадратни скоби]." "invalid_chars": "Потребителското име може да съдържа само букви, цифри, интервали, долни черти и [квадратни скоби]."
}, },
"host_modal": { "host_modal": {
"title": "Частно лоби", "title": "Частна игра",
"map": "Карта",
"difficulty": "Трудност",
"options_title": "Опции", "options_title": "Опции",
"bots": "Ботове: ", "bots": "Ботове: ",
"bots_disabled": "Изключено", "bots_disabled": "Изключено",
"disable_nations": "Изключване на нации", "disable_nations": "Изключване на нации",
"instant_build": "Незабавно изграждане", "instant_build": "Незабавно построяване",
"infinite_gold": "Безкрайно злато", "infinite_gold": "Безкрайно злато",
"infinite_troops": "Безкрайни войници", "infinite_troops": "Безкрайна популация",
"disable_nukes": "Изключване на ядрени оръжия", "disable_nukes": "Изключване на ядрени оръжия",
"player": "Играч", "player": "Играч",
"players": "Играчи", "players": "Играчи",
"waiting": "Изчакване на играчи...", "waiting": "Изчакване на играчи...",
"start": "Започване на игра" "start": "Започване на игра",
"mode": "Начин на игра"
}, },
"difficulty": { "difficulty": {
"Relaxed": "Релаксирано", "Relaxed": "Релаксирано",
"Balanced": "Балансирано", "Balanced": "Балансирано",
"Intense": "Интензивно", "Intense": "Интензивно",
"Impossible": "Невъзможно" "Impossible": "Невъзможно",
"difficulty": "Трудност"
},
"game_starting_modal": {
"title": "Играта се стартира...",
"desc": "Подготвяне за стартиране на лобито. Моля, изчакайте."
},
"lang": {
"en": "Bulgarian",
"native": "Български",
"svg": "bg",
"lang_code": "bg"
},
"game_mode": {
"ffa": "Свободна игра (FFA)",
"teams": "Отбори"
} }
} }
+93 -83
View File
@@ -1,103 +1,101 @@
{ {
"main": { "main": {
"join_discord": "Tritt dem Discord bei!", "join_discord": "Tritt dem Discord bei!",
"create_lobby": "Lobby Erstellen", "create_lobby": "Lobby erstellen",
"join_lobby": "Lobby Beitreten", "join_lobby": "Lobby beitreten",
"single_player": "Einzelspieler", "single_player": "Einzelspieler",
"instructions": "Anleitung", "instructions": "Anleitung",
"how_to_play": "Wie man Spielt", "how_to_play": "Wie man Spielt",
"wiki": "Wiki" "wiki": "Wiki"
}, },
"help_modal": { "help_modal": {
"hotkeys": "Kurzbefehle", "hotkeys": "Tastaturbelegungen",
"table_key": "Taste", "table_key": "Tastenkombination",
"table_action": "Aktion", "table_action": "Aktion",
"action_alt_view": "Alternative Sicht (Terrain/Länder)", "action_alt_view": "Alternative Ansicht anzeigen (Gebiete/Länder)",
"action_attack_altclick": "Angreifen (wenn links klick auf Menü öffnen eingestellt ist)", "action_attack_altclick": "Angriff ausführen (wenn Linksklick auf \"öffne Menü\" gestellt ist)",
"action_build": "Baumenü öffnen", "action_build": "Baumenü öffnen",
"action_center": "Spieler zentrieren", "action_center": "Karte auf Spieler zentrieren",
"action_zoom": "Raus/Rein zoomen", "action_zoom": "Ansicht vergrößern/verkleinern",
"action_move_camera": "Sichtfeld (Kamera) bewegen", "action_move_camera": "Karte verschieben",
"action_ratio_change": " Angriffsverhältnis verringern/erhöhen", "action_ratio_change": "Angriffsrate verringern/erhöhen",
"action_reset_gfx": "Grafik zurücksetzen", "action_reset_gfx": "Grafik zurücksetzen",
"ui_section": "Spiel UI", "ui_section": "Spieloberfläche",
"ui_leaderboard": "Bestenliste", "ui_leaderboard": "Bestenliste",
"ui_leaderboard_desc": "Zeigt die top-Spieler des Spiels und deren Namen, Landbesitz in % sowie deren Gold", "ui_leaderboard_desc": "Zeigt die Namen, % an besetzter Landfläche und Gold der stärksten Spieler im Spiel an.",
"ui_control": "Bedienfeld", "ui_control": "Aktionsmenü",
"ui_control_desc": "Das Bedienfeld enthält die folgenden Elemente:", "ui_control_desc": "Der Kontrollbereich beinhaltet folgende Elemente:",
"ui_pop": "Pop - Die Anzahl der eigenen Einheiten, die maximale Bevölkerung und die und die Bevölkerungswachstumsrate.", "ui_pop": "Bevölkerung - Die Anzahl der aktuellen Einheiten, die maximale Bevölkerungszahl und die Geschwindigkeit mit der man neue Einheiten bekommst.",
"ui_gold": "Gold - Die Menge eigenen Golds und die Rate in der es gewonnen wird.", "ui_gold": "Gold - Die aktuelle Menge an Gold, und die Geschwindigkeit mit der man Gold bekommt.",
"ui_troops_workers": "Truppen und Arbeiter - Die Menge an zugeteilten Truppen und Arbeitern. Truppen werden genutzt, um anzugreifen oder sich gegen Angriffe zu verteidigen. Arbeiter werden genutzt, um Gold zu generieren. Die Anzahl der Truppen und Arbeiter kann mithilfe des Schiebereglers angepasst werden.", "ui_troops_workers": "Truppen und Arbeiter - Die Menge der zugewiesenen Truppen und Arbeiter. Truppen werden zum Angriff oder zur Verteidigung gegen Angriffe eingesetzt. Arbeiter erzeugen Gold. Die Anzahl der Truppen und Arbeiter kann mit dem Schieberegler eingestellt werden.",
"ui_attack_ratio": "Angriffsverhältnis - Die Menge an Truppen, die zum Angriff verwendet werden. Das Angriffsverhältnis kann mithilfe des Schiebereglers angepasst werden.", "ui_attack_ratio": "Angriffsrate - Die Anzahl der Truppen welche für Angriffe verwendet werden. Die Angriffsrate kann über den Schieberegler eingestellt werden.",
"ui_options": "Optionen", "ui_options": "Optionen",
"ui_options_desc": "Die folgenden Elemente können in den Optionen gefunden werden:", "ui_options_desc": "Die folgenden Schaltflächen sind in den Optionen verfügbar:",
"option_pause": "Pausieren/Abspielen des Spiels - Nur im Einzelspielermodus verfügbar.", "option_pause": "Spiel pausieren/fortsetzen - Nur im Einzelspieler möglich.",
"option_timer": "Timer - Vergangene Zeit seit Beginn des Spiels.", "option_timer": "Spieluhr - Vergangene Zeit seit Spielbeginn.",
"option_exit": "Exit-Taste.", "option_exit": "Spiel verlassen.",
"option_settings": "Einstellungen - Das Einstellungs-Menü öffnen. Dort kann die Alternative Sichtweise, der Dunkle Modus, Emojis und die Aktion bei einem Linksclick umgeschaltet werden.", "option_settings": "Einstellungen - Öffnet die Spieleinstellungen. Dort können die alternative Kartenansicht, der Dunkle Modus, Emojis und Aktion beim Linksklick eingestellt werden",
"radial_title": "Radialmenü", "radial_title": "Radialmenü",
"radial_desc": "Ein Rechtsclick (oder tippen auf Mobilgeräten) öffnet das Radialmenü. Dort gibt es folgende Optionen:", "radial_desc": "Rechtsklick (bei Berührung auf Mobilgeräten) öffnet das Aktionsmenü. Von dort kann man:",
"radial_build": "Das Baumenü öffnen.", "radial_build": "Das Baumenü öffnen.",
"radial_info": "Das Infomenü offnen", "radial_info": "Den Infobereich öffnen.",
"radial_boat": "Ein Boot zum Angriff des ausgewählten Standortes (nur verfügbar, wenn Wasser zugänglich ist).", "radial_boat": "Ein Boot zum Angriff auf das gewählte Gebiet schicken (nur verfügbar bei Zugang zu Wasser).",
"radial_close": "Das Menü schließen.", "radial_close": "Das Menü schließen.",
"info_title": "Infomenü", "info_title": "Infobereich",
"info_enemy_desc": "Enthält Informationen wie der ausgewählte Spielername, Gold, Truppen, und, ob der Spieler ein Verräter ist. Verräter ist ein Spieler, welcher einen verbündeten Spieler verraten (angegriffen) hat. Die Symbole unten repräsentieren die folgenden Interaktionen:", "info_enemy_desc": "Beinhaltet Informationen wie den Namen, Gold und Truppen für den Spieler. Zeigt zusätzlich an ob der Spieler ein Verräter ist. Ein Verräter ist ein Spieler welcher ein Bündnis gebrochen und seinen Verbündeten angegriffen hat. Die folgenden Icons stehen für folgende Aktionen:",
"info_target": "Eine Zielmarkierung auf einen Spieler setzen, markiert den Spieler für alle verbündeten, zum koordinieren von Angriffen.", "info_target": "Platziert eine Zielscheibe auf dem Spieler, als Markierung für alle Verbündeten zur Koordination von gemeinsamen Angriffen.",
"info_alliance": "Eine Verbündungsanfrage an den Spieler senden. Verbündete können Ressourcen und Truppen teilen, aber können sich nicht gegenseitig angreifen.", "info_alliance": "Sendet eine Bündnis-Anfrage an den Spieler. Verbündete können Ressourcen und Truppen teilen, sich aber nicht gegenseitig angreifen.",
"info_emoji": "Einen Emoji an den Spieler senden.", "info_emoji": "Sendet ein Emoji an den Spieler.",
"info_ally_panel": "Verbündeten-Infomenü", "info_ally_panel": "Bündnis Infobereich",
"info_ally_desc": "Wenn du dich mit einem Spieler verbündest, werden die folgenden neuen Symbole freigeschaltet:", "info_ally_desc": "Wenn man sich mit einem Spieler verbündet werden die folgenden Icons sichtbar:",
"ally_betray": "Den Verbündeten verraten, beendet das Bündnis. Nun wirst du ein permanentes Symbol neben deinem Namen haben. Bots haben eine geringere Wahrscheinlichkeit, sich mit dir zu verbünden und Spieler denken lieber zweimal nach.", "ally_betray": "Verrät den Verbündeten, was das Bündnis beendet. Hat eine permanente Markierung als Verräter zur Folge. Bots werden seltener Bündnisse mit Verrätern eingehen und menschliche Spieler sich es zweimal überlegen mit einem Verräter verbündet zu sein.",
"ally_donate": "Spende einige der eigenen Truppen zu deinem Verbündeten. Wird genutzt, wenn dieser wenige Truppen hat und angregriffen wird, oder wenn dieser die extra-Kraft braucht, um einen Gegner zu zerschlagen.", "ally_donate": "Teile einige Truppen mit dem verbündeten Spieler. Kann benutzt werden, um einen angegriffenen Verbündeten mit Truppen zu helfen oder diesem bei einem vernichtenden Schlag gegen einen Feind zu unterstützen.",
"build_menu_title": "Baumenü", "build_menu_title": "Baumenü",
"build_name": "Name", "build_name": "Name",
"build_icon": "Symbol", "build_icon": "Icon",
"build_desc": "Beschreibung", "build_desc": "Beschreibung",
"build_city": "Stadt", "build_city": "Stadt",
"build_city_desc": "Erhöht die maximale Bevölkerung. Hilfreich, wenn du nicht mehr expandieren kannst oder kurz davor bist, dein Bevölkerungslimit zu erreichen.", "build_city_desc": "Erhöht die maximale Bevölkerungsanzahl. Nützlich, wenn das eigene Territorium nicht erweitert werden kann oder das Bevölkerungslimit erreicht wird.",
"build_defense": "Verteidigungsposten", "build_defense": "Verteidigungsposten",
"build_defense_desc": "Erhöht die Verteidigung an nahe gelegenen Grenzen. Angriffe von Gegnern sind langsamer und haben mehr Verluste.", "build_defense_desc": "Erhöht die Verteidigung von anliegenden Grenzen. Angriffe von Feinden sind langsamer und sorgen für mehr Verluste des Feindes.",
"build_port": "Hafen", "build_port": "Hafen",
"build_port_desc": "Sendet automatisch Handelsschiffe zwischen Häfen deines Landes und anderen Ländern (außer wenn du \"Handel beenden\" für den Spieler geclickt hast oder diese den Handel mit dir beendet haben), dabei erhalten beide Seiten Gold. Ermöglicht es, Schlachtschiffe zu bauen. Kann nur nahe am Wasser gebaut werden.", "build_port_desc": "Sendet automatisch Handelsschiffe zwischen eigenen Häfen und denen anderer Länder (außer es wurde bei oder von einem anderen Spieler \"Handel stoppen\" im Infobereich geklickt), welche Gold für beide Seiten einbringen. Ermöglicht den Bau von Kriegsschiffen. Kann nur in der Nähe von Wasser gebaut werden.",
"build_warship": "Schlachtschiff", "build_warship": "Kriegsschiff",
"build_warship_desc": "Patroulliert in einem Bereich, fängt Handelsschiffe ein und zerstört gegnerische Schlachtschiffe und Boote. Wird vom nächsten Hafen hervorgebracht und patroulliert den Bereich, den du anfangs geclickt hast.", "build_warship_desc": "Patrouilliert einen Bereich, kapert Handelsschiffe und zerstört befeindete Kriegsschiffe sowie Boote. Erscheint beim nächstgelegenen Hafen und patrouilliert anschließend um den Punkt wo es gebaut wurde.",
"build_silo": "Raketensilo", "build_silo": "Raketensilo",
"build_silo_desc": "Ermöglicht das Starten von Raketen (Geschossen).", "build_silo_desc": "Ermöglicht das Abfeuern von Raketen und Bomben.",
"build_sam": "Flugabwehrrakete (SAM)", "build_sam": "Flugabwehr",
"build_sam_desc": "Hat eine 75% Wahrscheinlichkeit, gegenerische Raketen in einem Radius von 100 Pixeln abzufangen. Die Flugabwehrrakete besitzt eine 7,5 Sekunden Abklingzeit und kann keine MIRVs abfangen.", "build_sam_desc": "Hat eine 75% Chance feindliche Raketen und Bomben in einem 100 Pixel Radius abzufangen. Die Flugabwehr hat eine 7,5 Sekunden Abklingzeit und kann keine MIRVs abfangen.",
"build_atom": "Atombombe", "build_atom": "Atombombe",
"build_atom_desc": "Kleine explosive Bombe, die Territorium zerstört, Gebde, Schiffe und Boote. Startet vom nächsten Raketensilo und landet in dem Bereich, den du anfangs geclickt hast.", "build_atom_desc": "Bombe für eine kleine Explosion, die Territorium, Gebäude, Schiffe und Boote zerstört. Wird vom nächstgelegenen Raketensilo abgefeuert und schlägt am Punkt wo sie gebaut wurde ein.",
"build_hydrogen": "Wasserstoffbombe", "build_hydrogen": "Wasserstoffbombe",
"build_hydrogen_desc": "Große explosive Bombe. Startet vom nächsten Raketensilo und landet in dem Bereich, den du anfangs geclickt hast", "build_hydrogen_desc": "Bombe für eine große Explosion. Wird vom nächstgelegenen Raketensilo abgefeuert und schlägt am Punkt wo sie gebaut wurde ein.",
"build_mirv": "MIRV", "build_mirv": "MIRV",
"build_mirv_desc": "Die mächtigste Bombe im Spiel. Zerteilt sich in viele kleine Bomben, die einen großen bereich abdecken. Schadet nur dem Spieler, den du anfangs geclickt hast. Startet vom nächsten Raketensilo und landet in dem Bereich, den du anfangs geclickt hast.", "build_mirv_desc": "Die stärkste Bombe im Spiel. Teilt sich in kleinere Bomben auf, die auf vielen Gebieten einschlagen. Beschädigt nur den Spieler auf den beim Bau der Bombe geklickt wurde. Wird vom nächstgelegenen Raketensilo abgefeuert und schlägt am Punkt wo sie gebaut wurde ein.",
"player_icons": "Spielersymbole", "player_icons": "Spieler-Icons",
"icon_desc": "Beispiele einiger Symbole, denen du begegnen wirst und was diese bedeuten:", "icon_desc": "Beispiele zu einigen Icons während des Spielens und ihre Bedeutung:",
"icon_crown": "Krone - Dies ist der Spieler mit dem meisten Territorium.", "icon_crown": "Krone - Dieser Spieler ist auf Platz 1 der Bestenliste.",
"icon_traitor": "Überkreuzte Schwerter - Verräter. Dieser Spieler hat einen Verbündeten angegriffen.", "icon_traitor": "Gekreuzte Schwerter - Verräter. Dieser Spieler hat einen Verbündeten verraten und angegriffen.",
"icon_ally": "Handschlag - Verbündeter. Dieser Spieler ist mit dir verbündet.", "icon_ally": "Handschlag - Verbündeter. Dieser Spieler ist ein Verbündeter.",
"info_enemy_panel": "Gegner-Infomenü" "info_enemy_panel": "Gegner-Infobereich"
}, },
"single_modal": { "single_modal": {
"title": "Einzelspieler", "title": "Einzelspieler",
"map": "Karte",
"difficulty": "Schwierigkeit",
"allow_alliances": "Bündnisse erlauben", "allow_alliances": "Bündnisse erlauben",
"options_title": "Optionen", "options_title": "Optionen",
"bots": "Bots: ", "bots": "Bots: ",
"bots_disabled": "Deaktiviert", "bots_disabled": "Deaktiviert",
"disable_nations": "Nationen deaktivieren", "disable_nations": "Nationen deaktivieren",
"instant_build": "Sofortiges Bauen", "instant_build": "Sofortiges Bauen",
"infinite_gold": "Unendliches Gold", "infinite_gold": "Unendlich Gold",
"infinite_troops": "Unendliche Truppen", "infinite_troops": "Unendlich Truppen",
"disable_nukes": "Bomben deaktivieren", "disable_nukes": "Atomwaffen deaktivieren",
"start": "Spiel starten" "start": "Spiel starten"
}, },
"map": { "map": {
"world": "Welt", "world": "Welt",
"europe": "Europa", "europe": "Europa",
"mena": "MENA (Nahost und Nordafrika)", "mena": "MENA",
"northamerica": "Nordamerika", "northamerica": "Nordamerika",
"oceania": "Ozeanien", "oceania": "Ozeanien",
"blacksea": "Schwarzes Meer", "blacksea": "Schwarzes Meer",
@@ -110,53 +108,65 @@
"australia": "Australien", "australia": "Australien",
"random": "Zufällig", "random": "Zufällig",
"iceland": "Island", "iceland": "Island",
"pangaea": "Pangaea" "pangaea": "Pangaea",
"map": "Karte",
"betweentwoseas": "Zwischen zwei Meeren",
"japanandneighbors": "Japan und Nachbarländer"
}, },
"private_lobby": { "private_lobby": {
"title": "Privater Lobby beitreten", "title": "Privater Lobby beitreten",
"enter_id": "Lobby ID eingeben", "enter_id": "Lobby ID eingeben",
"player": "Spieler", "player": "Spieler",
"players": "Spieler", "players": "Spieler",
"join_lobby": "Lobby Beitreten", "join_lobby": "Lobby beitreten",
"checking": "Lobby wird überprüft...", "checking": "Überprüfe Lobby...",
"not_found": "Lobby nicht gefunden. Bitte überprüfe die ID und versuche es erneut.", "not_found": "Lobby nicht gefunden. Bitte Lobby ID überprüfen und erneut versuchen.",
"error": "Ein Fehler ist aufgetreten. Bitte versuche es erneut.", "error": "Ein Fehler ist aufgetreten. Bitte erneut versuchen.",
"joined_waiting": "Erfolgreich beigetreten! Auf den Start des Spiels warten..." "joined_waiting": "Erfolgreich beigetreten! Warte auf den Start des Spiels..."
}, },
"public_lobby": { "public_lobby": {
"join": "Nächstem Spiel beitreten", "join": "Nächstem Spiel beitreten",
"waiting": "spieler warten" "waiting": "wartende Spieler"
}, },
"username": { "username": {
"enter_username": "Gib deinen Benutzernamen ein", "enter_username": "Benutzernamen eingeben",
"not_string": "Benutzername muss eine Zeichenkette sein.", "not_string": "Benutzername muss ein Text sein.",
"too_short": "Benutzername muss mindestens {min} zeichen enthalten.", "too_short": "Benutzername muss mindestens {min} Zeichen lang sein.",
"too_long": "Benutzername darf maximal {max} zeichen enthalten.", "too_long": "Benutzername darf {max} Zeichen nicht überschreiten.",
"invalid_chars": "Benutzername kann nur Buchstaben, Zahlen, Leerzeichen, Unterstriche und [eckige Klammern] enthalten." "invalid_chars": "Benutzername darf nur Buchstaben, Zahlen, Leerzeichen, Unterstriche und [eckige Klammer] enthalten."
}, },
"host_modal": { "host_modal": {
"title": "Private Lobby", "title": "Private Lobby",
"map": "Karte",
"difficulty": "Schwierigkeit",
"mode": "Modus",
"options_title": "Optionen", "options_title": "Optionen",
"bots": "Bots: ", "bots": "Bots:",
"bots_disabled": "Deaktiviert", "bots_disabled": "Deaktiviert",
"disable_nations": "Nationen deaktivieren", "disable_nations": "Nationen deaktivieren",
"instant_build": "Sofortiges Bauen", "instant_build": "Sofortiges Bauen",
"infinite_gold": "Unendliches Gold", "infinite_gold": "Unendlich Gold",
"infinite_troops": "Unendliche Truppen", "infinite_troops": "Unendlich Truppen",
"disable_nukes": "Bomben deaktivieren", "disable_nukes": "Atomwaffen deaktivieren",
"player": "Spieler", "player": "Spieler",
"players": "Spieler", "players": "Spieler",
"waiting": "Auf Spieler warten...", "waiting": "Warte auf Spieler...",
"start": "Spiel starten" "start": "Spiel starten",
"mode": "Modus"
}, },
"difficulty": { "difficulty": {
"Relaxed": "Entspannt", "Relaxed": "Entspannt",
"Balanced": "Ausgewogen", "Balanced": "Ausgeglichen",
"Intense": "Intensiv", "Intense": "Anspruchsvoll",
"Impossible": "Unmöglich" "Impossible": "Unmöglich",
"difficulty": "Schwierigkeitsgrad"
},
"game_starting_modal": {
"title": "Das Spiel startet...",
"desc": "Der Start der Lobby wird vorbereitet. Bitte warten."
},
"lang": {
"en": "German",
"native": "Deutsch",
"svg": "de",
"lang_code": "de"
}, },
"game_mode": { "game_mode": {
"ffa": "Free for All", "ffa": "Free for All",
+168
View File
@@ -0,0 +1,168 @@
{
"lang": {
"en": "debug",
"native": "debug",
"svg": "xx",
"lang_code": "debug"
},
"main": {
"join_discord": "main.join_discord",
"create_lobby": "main.create_lobby",
"join_lobby": "main.join_lobby",
"single_player": "main.single_player",
"instructions": "main.instructions",
"how_to_play": "main.how_to_play",
"wiki": "main.wiki"
},
"help_modal": {
"hotkeys": "help_modal.hotkeys",
"table_key": "help_modal.table_key",
"table_action": "help_modal.table_action",
"action_alt_view": "help_modal.action_alt_view",
"action_attack_altclick": "help_modal.action_attack_altclick",
"action_build": "help_modal.action_build",
"action_center": "help_modal.action_center",
"action_zoom": "help_modal.action_zoom",
"action_move_camera": "help_modal.action_move_camera",
"action_ratio_change": "help_modal.action_ratio_change",
"action_reset_gfx": "help_modal.action_reset_gfx",
"ui_section": "help_modal.ui_section",
"ui_leaderboard": "help_modal.ui_leaderboard",
"ui_leaderboard_desc": "help_modal.ui_leaderboard_desc",
"ui_control": "help_modal.ui_control",
"ui_control_desc": "help_modal.ui_control_desc",
"ui_pop": "help_modal.ui_pop",
"ui_gold": "help_modal.ui_gold",
"ui_troops_workers": "help_modal.ui_troops_workers",
"ui_attack_ratio": "help_modal.ui_attack_ratio",
"ui_options": "help_modal.ui_options",
"ui_options_desc": "help_modal.ui_options_desc",
"option_pause": "help_modal.option_pause",
"option_timer": "help_modal.option_timer",
"option_exit": "help_modal.option_exit",
"option_settings": "help_modal.option_settings",
"radial_title": "help_modal.radial_title",
"radial_desc": "help_modal.radial_desc",
"radial_build": "help_modal.radial_build",
"radial_info": "help_modal.radial_info",
"radial_boat": "help_modal.radial_boat",
"radial_close": "help_modal.radial_close",
"info_title": "help_modal.info_title",
"info_enemy_desc": "help_modal.info_enemy_desc",
"info_target": "help_modal.info_target",
"info_alliance": "help_modal.info_alliance",
"info_emoji": "help_modal.info_emoji",
"info_ally_panel": "help_modal.info_ally_panel",
"info_ally_desc": "help_modal.info_ally_desc",
"ally_betray": "help_modal.ally_betray",
"ally_donate": "help_modal.ally_donate",
"build_menu_title": "help_modal.build_menu_title",
"build_name": "help_modal.build_name",
"build_icon": "help_modal.build_icon",
"build_desc": "help_modal.build_desc",
"build_city": "help_modal.build_city",
"build_city_desc": "help_modal.build_city_desc",
"build_defense": "help_modal.build_defense",
"build_defense_desc": "help_modal.build_defense_desc",
"build_port": "help_modal.build_port",
"build_port_desc": "help_modal.build_port_desc",
"build_warship": "help_modal.build_warship",
"build_warship_desc": "help_modal.build_warship_desc",
"build_silo": "help_modal.build_silo",
"build_silo_desc": "help_modal.build_silo_desc",
"build_sam": "help_modal.build_sam",
"build_sam_desc": "help_modal.build_sam_desc",
"build_atom": "help_modal.build_atom",
"build_atom_desc": "help_modal.build_atom_desc",
"build_hydrogen": "help_modal.build_hydrogen",
"build_hydrogen_desc": "help_modal.build_hydrogen_desc",
"build_mirv": "help_modal.build_mirv",
"build_mirv_desc": "help_modal.build_mirv_desc",
"player_icons": "help_modal.player_icons",
"icon_desc": "help_modal.icon_desc",
"icon_crown": "help_modal.icon_crown",
"icon_traitor": "help_modal.icon_traitor",
"icon_ally": "help_modal.icon_ally",
"info_enemy_panel": "help_modal.info_enemy_panel"
},
"single_modal": {
"title": "single_modal.title",
"allow_alliances": "single_modal.allow_alliances",
"options_title": "single_modal.options_title",
"bots": "single_modal.bots",
"bots_disabled": "single_modal.bots_disabled",
"disable_nations": "single_modal.disable_nations",
"instant_build": "single_modal.instant_build",
"infinite_gold": "single_modal.infinite_gold",
"infinite_troops": "single_modal.infinite_troops",
"disable_nukes": "single_modal.disable_nukes",
"start": "single_modal.start"
},
"map": {
"map": "map.map",
"world": "map.world",
"europe": "map.europe",
"mena": "map.mena",
"northamerica": "map.northamerica",
"oceania": "map.oceania",
"blacksea": "map.blacksea",
"africa": "map.africa",
"asia": "map.asia",
"mars": "map.mars",
"southamerica": "map.southamerica",
"britannia": "map.britannia",
"gatewaytotheatlantic": "map.gatewaytotheatlantic",
"australia": "map.australia",
"random": "map.random",
"iceland": "map.iceland",
"pangaea": "map.pangaea"
},
"private_lobby": {
"title": "private_lobby.title",
"enter_id": "private_lobby.enter_id",
"player": "private_lobby.player",
"players": "private_lobby.players",
"join_lobby": "private_lobby.join_lobby",
"checking": "private_lobby.checking",
"not_found": "private_lobby.not_found",
"error": "private_lobby.error",
"joined_waiting": "private_lobby.joined_waiting"
},
"public_lobby": {
"join": "public_lobby.join",
"waiting": "public_lobby.waiting"
},
"username": {
"enter_username": "username.enter_username",
"not_string": "username.not_string",
"too_short": "username.too_short",
"too_long": "username.too_long",
"invalid_chars": "username.invalid_chars"
},
"host_modal": {
"title": "host_modal.title",
"options_title": "host_modal.options_title",
"bots": "host_modal.bots",
"bots_disabled": "host_modal.bots_disabled",
"disable_nations": "host_modal.disable_nations",
"instant_build": "host_modal.instant_build",
"infinite_gold": "host_modal.infinite_gold",
"infinite_troops": "host_modal.infinite_troops",
"disable_nukes": "host_modal.disable_nukes",
"player": "host_modal.player",
"players": "host_modal.players",
"waiting": "host_modal.waiting",
"start": "host_modal.start"
},
"game_starting_modal": {
"title": "game_starting_modal.title",
"desc": "game_starting_modal.desc"
},
"difficulty": {
"difficulty": "difficulty.difficulty",
"Relaxed": "difficulty.Relaxed",
"Balanced": "difficulty.Balanced",
"Intense": "difficulty.Intense",
"Impossible": "difficulty.Impossible"
}
}
+12 -4
View File
@@ -1,4 +1,10 @@
{ {
"lang": {
"en": "English",
"native": "English",
"svg": "xx",
"lang_code": "en"
},
"main": { "main": {
"title": "OpenFront (ALPHA)", "title": "OpenFront (ALPHA)",
"join_discord": "Join the Discord!", "join_discord": "Join the Discord!",
@@ -82,8 +88,6 @@
}, },
"single_modal": { "single_modal": {
"title": "Single Player", "title": "Single Player",
"map": "Map",
"difficulty": "Difficulty",
"allow_alliances": "Allow alliances", "allow_alliances": "Allow alliances",
"options_title": "Options", "options_title": "Options",
"bots": "Bots: ", "bots": "Bots: ",
@@ -96,6 +100,7 @@
"start": "Start Game" "start": "Start Game"
}, },
"map": { "map": {
"map": "Map",
"world": "World", "world": "World",
"europe": "Europe", "europe": "Europe",
"mena": "MENA", "mena": "MENA",
@@ -140,8 +145,6 @@
}, },
"host_modal": { "host_modal": {
"title": "Private Lobby", "title": "Private Lobby",
"map": "Map",
"difficulty": "Difficulty",
"mode": "Mode", "mode": "Mode",
"options_title": "Options", "options_title": "Options",
"bots": "Bots: ", "bots": "Bots: ",
@@ -156,7 +159,12 @@
"waiting": "Waiting for players...", "waiting": "Waiting for players...",
"start": "Start Game" "start": "Start Game"
}, },
"game_starting_modal": {
"title": "Game is Starting...",
"desc": "Preparing for the lobby to start. Please wait."
},
"difficulty": { "difficulty": {
"difficulty": "Difficulty",
"Relaxed": "Relaxed", "Relaxed": "Relaxed",
"Balanced": "Balanced", "Balanced": "Balanced",
"Intense": "Intense", "Intense": "Intense",
+2 -1
View File
@@ -2,7 +2,8 @@
"lang": { "lang": {
"en": "Spanish", "en": "Spanish",
"native": "Español", "native": "Español",
"svg": "es" "svg": "es",
"lang_code": "es"
}, },
"main": { "main": {
"join_discord": "¡Únete al Discord!", "join_discord": "¡Únete al Discord!",
+8 -4
View File
@@ -1,4 +1,10 @@
{ {
"lang": {
"en": "French",
"native": "Français",
"svg": "fr",
"lang_code": "fr"
},
"main": { "main": {
"join_discord": "Rejoignez le Discord !", "join_discord": "Rejoignez le Discord !",
"create_lobby": "Créer un Salon", "create_lobby": "Créer un Salon",
@@ -91,8 +97,6 @@
}, },
"single_modal": { "single_modal": {
"title": "Joueur seul", "title": "Joueur seul",
"map": "Carte",
"difficulty": "Difficulté",
"allow_alliances": "Autoriser les alliances", "allow_alliances": "Autoriser les alliances",
"options_title": "Options", "options_title": "Options",
"bots": "Bots : ", "bots": "Bots : ",
@@ -105,6 +109,7 @@
"start": "Commencer la partie" "start": "Commencer la partie"
}, },
"map": { "map": {
"map": "Carte",
"world": "Monde", "world": "Monde",
"europe": "Europe", "europe": "Europe",
"mena": "MENA", "mena": "MENA",
@@ -145,8 +150,6 @@
}, },
"host_modal": { "host_modal": {
"title": "Salon privé", "title": "Salon privé",
"map": "Carte",
"difficulty": "Difficulté",
"options_title": "Options", "options_title": "Options",
"bots": "Bots : ", "bots": "Bots : ",
"bots_disabled": "Désactivé", "bots_disabled": "Désactivé",
@@ -161,6 +164,7 @@
"start": "Commencer la partie" "start": "Commencer la partie"
}, },
"difficulty": { "difficulty": {
"difficulty": "Difficulté",
"Relaxed": "Détendu", "Relaxed": "Détendu",
"Balanced": "Équilibré", "Balanced": "Équilibré",
"Intense": "Intense", "Intense": "Intense",
+20 -3
View File
@@ -1,4 +1,10 @@
{ {
"lang": {
"en": "Japanese",
"native": "日本語",
"svg": "jp",
"lang_code": "ja"
},
"main": { "main": {
"join_discord": "Discordサーバーに参加!", "join_discord": "Discordサーバーに参加!",
"create_lobby": "ロビーを作成", "create_lobby": "ロビーを作成",
@@ -42,6 +48,7 @@
"radial_boat": "ボートを送る(海にアクセスできる場合)。", "radial_boat": "ボートを送る(海にアクセスできる場合)。",
"radial_close": "メニューを閉じる。", "radial_close": "メニューを閉じる。",
"info_title": "情報メニュー", "info_title": "情報メニュー",
"info_enemy_panel": "他国情報パネル",
"info_enemy_desc": "選択プレイヤーの名前、資産、兵士数、裏切り者かどうかを表示。裏切り者とは、同盟を結んでいたプレイヤーを裏切り、攻撃したプレイヤーのことです。以下のアイコンは、以下のやりとりを表しています:", "info_enemy_desc": "選択プレイヤーの名前、資産、兵士数、裏切り者かどうかを表示。裏切り者とは、同盟を結んでいたプレイヤーを裏切り、攻撃したプレイヤーのことです。以下のアイコンは、以下のやりとりを表しています:",
"info_target": "ターゲットマークを付ける(攻撃協調用)。", "info_target": "ターゲットマークを付ける(攻撃協調用)。",
"info_alliance": "同盟を申し込む。同盟国は資源と兵力を共有できますが、互いに攻撃することはできません。", "info_alliance": "同盟を申し込む。同盟国は資源と兵力を共有できますが、互いに攻撃することはできません。",
@@ -94,6 +101,7 @@
"start": "ゲーム開始" "start": "ゲーム開始"
}, },
"map": { "map": {
"map": "マップ",
"world": "世界", "world": "世界",
"europe": "ヨーロッパ", "europe": "ヨーロッパ",
"mena": "中東・北アフリカ", "mena": "中東・北アフリカ",
@@ -109,6 +117,7 @@
"australia": "オーストラリア", "australia": "オーストラリア",
"iceland": "アイスランド", "iceland": "アイスランド",
"japan": "日本とその近隣", "japan": "日本とその近隣",
"pangaea": "パンゲア",
"random": "ランダム" "random": "ランダム"
}, },
"private_lobby": { "private_lobby": {
@@ -130,13 +139,12 @@
"enter_username": "ユーザー名を入力", "enter_username": "ユーザー名を入力",
"not_string": "ユーザー名は文字列で入力してください。", "not_string": "ユーザー名は文字列で入力してください。",
"too_short": "ユーザー名は{min}文字より長い必要があります。", "too_short": "ユーザー名は{min}文字より長い必要があります。",
"too_long": "ユーザー名は{max}文字より短い必要があります", "too_long": "ユーザー名は{max}文字より短い必要があります",
"invalid_chars": "ユーザー名には英字、数字、スペース、アンダースコア、および [角括弧] のみ使用できます。" "invalid_chars": "ユーザー名には英字、数字、スペース、アンダースコア、および [角括弧] のみ使用できます。"
}, },
"host_modal": { "host_modal": {
"title": "プライベートロビー", "title": "プライベートロビー",
"map": "マップ", "mode": "モード",
"difficulty": "難易度",
"allow_alliances": "同盟を許可", "allow_alliances": "同盟を許可",
"options_title": "オプション", "options_title": "オプション",
"bots": "ボット数: ", "bots": "ボット数: ",
@@ -151,10 +159,19 @@
"waiting": "他のプレイヤーの参加を待っています...", "waiting": "他のプレイヤーの参加を待っています...",
"start": "ゲーム開始" "start": "ゲーム開始"
}, },
"game_starting_modal": {
"title": "ゲーム開始中...",
"desc": "スタートのためにロビー準備中... ちょっとまってね!"
},
"difficulty": { "difficulty": {
"difficulty": "難易度",
"Relaxed": "簡単", "Relaxed": "簡単",
"Balanced": "普通", "Balanced": "普通",
"Intense": "難しい", "Intense": "難しい",
"Impossible": "不可能" "Impossible": "不可能"
},
"game_mode": {
"ffa": "バトルロワイヤル",
"teams": "チーム戦"
} }
} }
+37 -24
View File
@@ -2,10 +2,10 @@
"main": { "main": {
"join_discord": "Word lid van de Discord!", "join_discord": "Word lid van de Discord!",
"create_lobby": "Lobby aanmaken", "create_lobby": "Lobby aanmaken",
"join_lobby": "Toetreden lobby", "join_lobby": "Lobby toetreden",
"single_player": "Enkele speler", "single_player": "Eén Speler",
"instructions": "Instructies", "instructions": "Instructies",
"how_to_play": "Hoe te spelen", "how_to_play": "Hoe spelen?",
"wiki": "Wiki" "wiki": "Wiki"
}, },
"help_modal": { "help_modal": {
@@ -21,8 +21,8 @@
"action_ratio_change": "Aanvalsverhouding verlagen/verhogen", "action_ratio_change": "Aanvalsverhouding verlagen/verhogen",
"action_reset_gfx": "Grafische instellingen herstellen", "action_reset_gfx": "Grafische instellingen herstellen",
"ui_section": "Spel-UI", "ui_section": "Spel-UI",
"ui_leaderboard": "Leaderboard (leidersbord)", "ui_leaderboard": "Leidersbord",
"ui_leaderboard_desc": "Toont de top spelers van het spel en hun namen, % bezette land en goud.", "ui_leaderboard_desc": "Toont de topspelers van het spel en hun namen, % bezette land en goud.",
"ui_control": "Controlepaneel", "ui_control": "Controlepaneel",
"ui_control_desc": "Het controlepaneel bevat de volgende elementen:", "ui_control_desc": "Het controlepaneel bevat de volgende elementen:",
"ui_pop": "Pop - Jouw totale bevolking, jouw maximale bevolking en de snelheid waarmee je ze verwerft.", "ui_pop": "Pop - Jouw totale bevolking, jouw maximale bevolking en de snelheid waarmee je ze verwerft.",
@@ -31,7 +31,7 @@
"ui_attack_ratio": "Aanvalsverhouding - Het aantal troepen dat wordt gebruikt bij een aanval. Je kunt de aanvalsverhouding aanpassen met de schuifbalk.", "ui_attack_ratio": "Aanvalsverhouding - Het aantal troepen dat wordt gebruikt bij een aanval. Je kunt de aanvalsverhouding aanpassen met de schuifbalk.",
"ui_options": "Opties", "ui_options": "Opties",
"ui_options_desc": "De volgende elementen zijn hierin te vinden:", "ui_options_desc": "De volgende elementen zijn hierin te vinden:",
"option_pause": "Spel pauzeren/hervatten - Alleen beschikbaar in enkele-speler modus.", "option_pause": "Spel pauzeren/hervatten - Alleen beschikbaar in het speltype voor één speler.",
"option_timer": "Timer - Tijd verstreken sinds het begin van het spel.", "option_timer": "Timer - Tijd verstreken sinds het begin van het spel.",
"option_exit": "Afsluitknop.", "option_exit": "Afsluitknop.",
"option_settings": "Instellingen - Open het instellingenmenu. Daarin kun je de Alternatieve weergave, Donkere modus, Emoji's en actie bij linkermuisknop in- of uitschakelen.", "option_settings": "Instellingen - Open het instellingenmenu. Daarin kun je de Alternatieve weergave, Donkere modus, Emoji's en actie bij linkermuisknop in- of uitschakelen.",
@@ -67,28 +67,26 @@
"build_sam": "Luchtdoelraket (SAM)-lanceerder", "build_sam": "Luchtdoelraket (SAM)-lanceerder",
"build_sam_desc": "Heeft 75% kans om vijandelijke raketten binnen een straal van 100 pixels te onderscheppen. De SAM heeft een afkoeltijd van 7,5 seconden en kan geen MIRV's onderscheppen.", "build_sam_desc": "Heeft 75% kans om vijandelijke raketten binnen een straal van 100 pixels te onderscheppen. De SAM heeft een afkoeltijd van 7,5 seconden en kan geen MIRV's onderscheppen.",
"build_atom": "Atoombom", "build_atom": "Atoombom",
"build_atom_desc": "Kleine explosieve bom die gebied, gebouwen, schepen en boten vernietigt. Spawnt vanuit de dichtstbijzijnde Raketsilo en landt in het gebied waar je klikte om het te bouwen.", "build_atom_desc": "Kleine explosieve bom die gebied, gebouwen, schepen en boten vernietigt. Komt vanuit de dichtstbijzijnde Raketsilo en landt op de plek waar je hebt geklikt om het te bouwen.",
"build_hydrogen": "Waterstofbom", "build_hydrogen": "Waterstofbom",
"build_hydrogen_desc": "Grote explosieve bom. Spawnt vanuit de dichtstbijzijnde Raketsilo en landt in het gebied waar je klikte om het te bouwen.", "build_hydrogen_desc": "Grote explosieve bom. Komt vanuit de dichtstbijzijnde Raketsilo en landt op de plek waar je hebt geklikt om het te bouwen.",
"build_mirv": "MIRV", "build_mirv": "MIRV",
"build_mirv_desc": "De krachtigste bom in het spel. Splitst zich op in kleinere bommen die een enorm gebied dekken. Schaadt alleen de speler waarop je klikte om de bom te bouwen. Spawnt vanuit de dichtstbijzijnde Raketsilo en landt in het gebied waar je klikte om het te bouwen.", "build_mirv_desc": "De krachtigste bom in het spel. Splitst zich op in kleinere bommen die een enorm gebied dekken. Schaadt alleen de speler waarop je klikte om de bom te bouwen. Komt vanuit de dichtstbijzijnde Raketsilo en landt in al het gebied dat de speler had toen je de bom bouwde, en nog steeds heeft.",
"player_icons": "Spelersiconen", "player_icons": "Spelersiconen",
"icon_desc": "Voorbeelden van enkele iconen die je in het spel zult tegenkomen en wat ze betekenen:", "icon_desc": "Voorbeelden van enkele iconen die je in het spel zult tegenkomen en wat ze betekenen:",
"icon_crown": "Kroon - Dit is de nummer 1 speler op de leaderboard", "icon_crown": "Kroon - Dit is de nummer 1 speler op de leaderboard.",
"icon_traitor": "Gekruiste zwaarden - Verrader. Deze speler heeft een bondgenoot aangevallen.", "icon_traitor": "Gekruiste zwaarden - Verrader. Deze speler heeft een bondgenoot aangevallen.",
"icon_ally": "Handdruk - Bondgenoot. Deze speler is je bondgenoot.", "icon_ally": "Handdruk - Bondgenoot. Deze speler is je bondgenoot.",
"info_enemy_panel": "Infopaneel vijand" "info_enemy_panel": "Infopaneel vijand"
}, },
"single_modal": { "single_modal": {
"title": "Enkele speler", "title": "Eén speler",
"map": "Kaart",
"difficulty": "Moeilijkheidsgraad",
"allow_alliances": "Bondgenootschappen toestaan", "allow_alliances": "Bondgenootschappen toestaan",
"options_title": "Opties", "options_title": "Opties",
"bots": "Bots:", "bots": "Bots:",
"bots_disabled": "Uitgeschakeld", "bots_disabled": "Uitgeschakeld",
"disable_nations": "Naties uitschakelen", "disable_nations": "Naties uitschakelen",
"instant_build": "Bouw wachttijd afschaffen", "instant_build": "Bouwwachttijd uitschakelen",
"infinite_gold": "Oneindig goud", "infinite_gold": "Oneindig goud",
"infinite_troops": "Oneindige troepen", "infinite_troops": "Oneindige troepen",
"disable_nukes": "Kernwapens uitschakelen", "disable_nukes": "Kernwapens uitschakelen",
@@ -110,21 +108,22 @@
"australia": "Australië", "australia": "Australië",
"random": "Willekeurig", "random": "Willekeurig",
"iceland": "IJsland", "iceland": "IJsland",
"pangaea": "Pangea" "pangaea": "Pangea",
"map": "Kaart"
}, },
"private_lobby": { "private_lobby": {
"title": "Toedreden privé-lobby", "title": "Privélobby toetreden",
"enter_id": "Voer Lobby-ID in", "enter_id": "Voer Lobby-ID in",
"player": "Speler", "player": "Speler",
"players": "Spelers", "players": "Spelers",
"join_lobby": "Toedreden lobby", "join_lobby": "Lobby toetreden",
"checking": "Lobby controleren...", "checking": "Lobby controleren...",
"not_found": "Lobby niet gevonden. Controleer het ID en probeer het opnieuw.", "not_found": "Lobby niet gevonden. Controleer het ID en probeer het opnieuw.",
"error": "Er is een fout opgetreden. Probeer het opnieuw.", "error": "Er is een fout opgetreden. Probeer het opnieuw.",
"joined_waiting": "Succesvol toegetreden! Wachten tot het spel begint..." "joined_waiting": "Succesvol toegetreden! Wachten tot het spel begint..."
}, },
"public_lobby": { "public_lobby": {
"join": "Volgende spel toetreden", "join": "Deelnemen aan volgende Spel",
"waiting": "spelers wachten" "waiting": "spelers wachten"
}, },
"username": { "username": {
@@ -135,26 +134,40 @@
"invalid_chars": "Gebruikersnaam mag alleen letters, cijfers, spaties, underscores en [vierkante haakjes] bevatten." "invalid_chars": "Gebruikersnaam mag alleen letters, cijfers, spaties, underscores en [vierkante haakjes] bevatten."
}, },
"host_modal": { "host_modal": {
"title": "Privé lobby", "title": "Privélobby",
"map": "Kaart",
"difficulty": "Moeilijkheidsgraad",
"options_title": "Opties", "options_title": "Opties",
"bots": "Bots:", "bots": "Bots:",
"bots_disabled": "Uitgeschakeld", "bots_disabled": "Uitgeschakeld",
"disable_nations": "Naties uitschakelen", "disable_nations": "Naties uitschakelen",
"instant_build": "Bouw wachttijd afschaffen", "instant_build": "Bouwwachttijd uitschakelen",
"infinite_gold": "Oneindig goud", "infinite_gold": "Oneindig goud",
"infinite_troops": "Oneindige troepen", "infinite_troops": "Oneindige troepen",
"disable_nukes": "Kernwapens uitschakelen", "disable_nukes": "Kernwapens uitschakelen",
"player": "Speler", "player": "Speler",
"players": "Spelers", "players": "Spelers",
"waiting": "Wachten op spelers...", "waiting": "Wachten op spelers...",
"start": "Start Spel" "start": "Start Spel",
"mode": "Modus"
}, },
"difficulty": { "difficulty": {
"Relaxed": "Ontspannen", "Relaxed": "Ontspannen",
"Balanced": "Gebalanceerd", "Balanced": "Gebalanceerd",
"Intense": "Intens", "Intense": "Intens",
"Impossible": "Onmogelijk" "Impossible": "Onmogelijk",
"difficulty": "Moeilijkheidsgraad"
},
"game_starting_modal": {
"title": "Spel gaat starten...",
"desc": "Voorbereiden op het starten van de lobby. Even geduld."
},
"lang": {
"en": "Dutch",
"native": "Nederlands",
"svg": "nl",
"lang_code": "nl"
},
"game_mode": {
"ffa": "Iedereen tegen iedereen (FFA)",
"teams": "Teams"
} }
} }
+173
View File
@@ -0,0 +1,173 @@
{
"main": {
"join_discord": "Dołącz do Discord'a!",
"create_lobby": "Utwórz lobby",
"join_lobby": "Dołącz do lobby",
"single_player": "Gra jednoosobowa",
"instructions": "Instrukcje",
"how_to_play": "Jak grać",
"wiki": "Wiki"
},
"help_modal": {
"hotkeys": "Skróty klawiszowe",
"table_key": "Przycisk",
"table_action": "Akcja",
"action_alt_view": "Alternatywny widok (teren/państwa)",
"action_attack_altclick": "Atak (gdy lewy przycisk myszy jest ustawiony na otwieranie menu).",
"action_build": "Otwórz menu budowy",
"action_center": "Wyśrodkuj kamerę na graczu",
"action_zoom": "Oddal/Przybliż",
"action_move_camera": "Przesuń kamerę",
"action_ratio_change": "Zmniejsz/Zwiększ proporcje ataku",
"action_reset_gfx": "Zresetuj grafikę",
"ui_section": "Interfejs gry",
"ui_leaderboard": "Ranking",
"ui_leaderboard_desc": "Wyświetla najlepszych graczy w bieżącej rozgrywce wraz z ich nazwami, procentem kontrolowanych terytoriów i ilością posiadanego złota.",
"ui_control": "Panel sterowania",
"ui_control_desc": "Panel sterowania zawiera następujące elementy:",
"ui_pop": "Populacja Liczba posiadanych jednostek, maksymalna liczba ludności oraz tempo, w jakim ją zdobywasz.",
"ui_gold": "Złoto Liczba posiadanego złota oraz tempo jego przyrostu.",
"ui_troops_workers": "Wojsko i Pracownicy Liczba przydzielonych jednostek wojskowych i pracowników. Wojsko służy do ataku oraz obrony przed wrogimi atakami, a pracownicy są wykorzystywani do generowania złota. Możesz regulować ich liczbę za pomocą suwaka.",
"ui_attack_ratio": "Współczynnik ataku Liczba wojsk wykorzystywanych podczas ataku. Możesz dostosować ten współczynnik za pomocą suwaka.",
"ui_options": "Opcje",
"ui_options_desc": "Wewnątrz można znaleźć następujące elementy:",
"option_pause": "Wstrzymaj/Wznów grę dostępne tylko w trybie jednoosobowym.",
"option_timer": "Licznik czasu czas, który upłynął od początku gry.",
"option_exit": "Przycisk wyjścia.",
"option_settings": "Ustawienia otwiera menu ustawień, w którym możesz włączyć Alternatywny Widok, Tryb Ciemny, Emotikony oraz zmienić działanie lewego przycisku myszy.",
"radial_title": "Menu kołowe",
"radial_desc": "Kliknięcie prawym przyciskiem myszy (lub dotknięcie na urządzeniu mobilnym) otwiera menu kołowe. Z tego miejsca możesz:",
"radial_build": "Otwórz menu budowy.",
"radial_info": "Otwórz menu informacji.",
"radial_boat": "Wyślij statek z wojskiem, aby zaatakować w wybranej lokalizacji (dostępne tylko wtedy, gdy masz dostęp do wody).",
"radial_close": "Zamknij menu.",
"info_title": "Menu informacji",
"info_enemy_desc": "Zawiera informacje takie jak: nazwa gracza, ilość złota i wojska oraz czy gracz jest zdrajcą. Zdrajca jest to gracz, który zdradził oraz zaatakował gracza, z którym był w sojuszu. Poniższe ikony reprezentują następujące interakcje:",
"info_target": "Umieść znacznik celu na graczu, oznaczając go, wszyscy twoi sojusznicy dostają powiadomienie o planowanym ataku, jest to pomocne do koordynowania ataków.",
"info_alliance": "Wyślij prośbę o sojusz do gracza. Sojusznicy mogą przesyłać sobie zasoby oraz wojsko, ale nie mogą się nawzajem zaatakować.",
"info_emoji": "Wyślij emotkę do gracza.",
"info_ally_panel": "Panel informacji sojusznika",
"info_ally_desc": "Po nawiązaniu sojuszu z graczem dostępne stają się następujące nowe ikony:",
"ally_betray": "Zdradzając swojego sojusznika — kończysz z nim sojusz. Od tego momentu do końca gry posiadasz ikonę zdrajcy obok twojej nazwy użytkownika. Boty będą mniej skłonne do zawierania sojuszy z tobą, a gracze dwa razy się zastanowią, zanim to zrobią.",
"ally_donate": "Przekaż część swoich wojsk swojemu sojusznikowi. Używane, gdy brakuje mu wojsk i jest atakowany, lub gdy potrzebuje dodatkowej siły, aby pokonać wroga.",
"build_menu_title": "Menu budowy",
"build_name": "Nazwa",
"build_icon": "Ikonka",
"build_desc": "Opis",
"build_city": "Miasto",
"build_city_desc": "Zwiększa maksymalną populację. Przydatne, gdy nie możesz rozszerzyć swojego terytorium lub zbliżasz się do limitu populacji.",
"build_defense": "Punkt Obronny",
"build_defense_desc": "Zwiększa obronę wokół pobliskiej granicy. Atak wroga jest wtedy wolniejszy oraz angażuje więcej wojska do przejęcia terenu.",
"build_port": "Port",
"build_port_desc": "Automatycznie wysyła statki handlowe między portami twojego kraju a innymi krajami (chyba że klikniesz „zatrzymaj handel” lub inny gracz zrobi to względem ciebie), przynosząc złoto obu stronom. Umożliwia budowanie okrętów wojennych. Może być budowane tylko w pobliżu wody.",
"build_warship": "Okręt wojenny",
"build_warship_desc": "Patroluje wyznaczony obszar, przechwytując statki handlowe i niszcząc wrogie okręty wojenne oraz statki z wojskiem. Pojawia się przy porcie, który ma najbliższą drogę do obszaru wyznaczonego do patrolu.",
"build_silo": "Silos rakietowy",
"build_silo_desc": "Umożliwia odpalenie rakiet.",
"build_sam": "Wyrzutnia SAM",
"build_sam_desc": "Posiada 75% szans na przechwycenie wrogich pocisków w zasięgu 100 pikseli. SAM odnawia się co 7,5 sekundy i nie może przechwycić pocisku MIRV.",
"build_atom": "Bomba atomowa",
"build_atom_desc": "Mała bomba atomowa, która niszczy terytoria, budynki, okręty wojenne oraz łodzie z wojskiem. Wystrzeliwuje rakiety z tego silosu rakietowego, który ma najszybszą drogę do przebycia, aby zaatakować wybrany obszar.",
"build_hydrogen": "Bomba wodorowa",
"build_hydrogen_desc": "Duża bomba wodorowa. Wystrzeliwuje pociski z tego silosu rakietowego, który ma najszybszą drogę do przebycia, aby zaatakować wybrany obszar.",
"build_mirv": "MIRV",
"build_mirv_desc": "Najpotężniejsza bomba w grze, która dzieli się na wiele mniejszych bomb — pokrywają one ogromny zakres terytorium. Zadaje tylko obrażenie graczowi, na którego kliknąłeś, aby ją wysłać. Wystrzeliwuje pocisk z tego silosu rakietowego, który ma najszybszą drogę do przebycia, aby zaatakować.",
"player_icons": "Ikony graczy",
"icon_desc": "Przykłady niektórych ikon w grze, które możesz napotkać, oraz ich znaczenie:",
"icon_crown": "Korona — Jest to gracz numer 1 w rankingu",
"icon_traitor": "Skrzyżowane miecze — Zdrajca. Ten gracz atakował sojusznika.",
"icon_ally": "Uścisk dłoni — Sojusznik. Ten gracz jest twoim sojusznikiem.",
"info_enemy_panel": "Panel informacji o wrogu"
},
"single_modal": {
"title": "Gra jednoosobowa",
"allow_alliances": "Pozwól na sojusze",
"options_title": "Opcje",
"bots": "Boty: ",
"bots_disabled": "Wyłączone",
"disable_nations": "Wyłącz Państwa",
"instant_build": "Natychmiastowa budowa",
"infinite_gold": "Nieskończone złoto",
"infinite_troops": "Nieskończone wojsko",
"disable_nukes": "Wyłącz broń nuklearną",
"start": "Rozpocznij Grę"
},
"map": {
"world": "Świat",
"europe": "Europa",
"mena": "MENA",
"northamerica": "Ameryka Północna",
"oceania": "Oceania",
"blacksea": "Morze Czarne",
"africa": "Afryka",
"asia": "Azja",
"mars": "Mars",
"southamerica": "Ameryka Południowa",
"britannia": "Wyspy Brytyjskie",
"gatewaytotheatlantic": "Brama do Atlantyku",
"australia": "Australia",
"random": "Losowe",
"iceland": "Islandia",
"pangaea": "Pangea",
"map": "Mapa"
},
"private_lobby": {
"title": "Dołącz do prywatnego Lobby",
"enter_id": "Wprowadź ID Lobby",
"player": "Gracz",
"players": "Gracze",
"join_lobby": "Dołącz do Lobby",
"checking": "Sprawdzanie lobby...",
"not_found": "Lobby nie zostało znalezione. Proszę sprawdzić ID i spróbować ponownie.",
"error": "Wystąpił błąd. Proszę spróbować ponownie.",
"joined_waiting": "Dołączono pomyślnie! Oczekiwanie na rozpoczęcie gry..."
},
"public_lobby": {
"join": "Dołącz do następnej gry",
"waiting": "oczekujący gracze"
},
"username": {
"enter_username": "Wprowadź swoją nazwę użytkownika",
"not_string": "Nazwa użytkownika musi być ciągiem znaków.",
"too_short": "Nazwa użytkownika musi mieć co najmniej {min} znaków.",
"too_long": "Nazwa użytkownika nie może przekraczać {max} znaków.",
"invalid_chars": "Nazwa użytkownika może zawierać tylko litery, cyfry, spacje, podkreślenia i [nawiasy kwadratowe]."
},
"host_modal": {
"title": "Prywatne lobby",
"options_title": "Opcje",
"bots": "Boty: ",
"bots_disabled": "Wyłączone",
"disable_nations": "Wyłącz Państwa",
"instant_build": "Natychmiastowa budowa",
"infinite_gold": "Nieskończone złoto",
"infinite_troops": "Nieskończone wojsko",
"disable_nukes": "Wyłącz broń nuklearną",
"player": "Gracz",
"players": "Gracze",
"waiting": "Oczekiwanie na graczy...",
"start": "Rozpocznij grę",
"mode": "Tryb"
},
"difficulty": {
"Relaxed": "Zrelaksowany",
"Balanced": "Zbalansowany",
"Intense": "Intensywny",
"Impossible": "Niemożliwy",
"difficulty": "Poziom trudności"
},
"game_starting_modal": {
"title": "Gra się rozpoczyna...",
"desc": "Przygotowanie do uruchomienia lobby. Proszę czekać."
},
"lang": {
"en": "Polish",
"native": "Polski",
"svg": "pl",
"lang_code": "pl"
},
"game_mode": {
"ffa": "Darmowe dla wszystkich",
"teams": "Drużyny"
}
}
+175
View File
@@ -0,0 +1,175 @@
{
"main": {
"join_discord": "Присоединяйтесь к Discord!",
"create_lobby": "Создать лобби",
"join_lobby": "Присоединиться к лобби",
"single_player": "Одиночная игра",
"instructions": "Инструкции",
"how_to_play": "Как играть",
"wiki": "Вики"
},
"help_modal": {
"hotkeys": "Горячие клавиши",
"table_key": "Клавиша",
"table_action": "Действие",
"action_alt_view": "Альтернативный вид (ландшафт/страны)",
"action_attack_altclick": "Атака (если левая кнопка мыши назначена на открытие меню)",
"action_build": "Открыть меню строительства",
"action_center": "Центрировать камеру на игроке",
"action_zoom": "Отдалить/Приблизить",
"action_move_camera": "Перемещение камеры",
"action_ratio_change": "Уменьшить/Увеличить соотношение атаки",
"action_reset_gfx": "Сбросить графику",
"ui_section": "Игровой интерфейс",
"ui_leaderboard": "Таблица лидеров",
"ui_leaderboard_desc": "Показывает лучших игроков и их имена, % контролируемой территории и золото.",
"ui_control": "Панель управления",
"ui_control_desc": "Панель управления содержит следующие элементы:",
"ui_pop": "Население — количество ваших подразделений, максимальное население и темп его роста.",
"ui_gold": "Золото — Количество золота и скорость, с которой вы его получаете.",
"ui_troops_workers": "Войска и Рабочие — Количество распределённых войск и рабочих. Войска используются для атаки или защиты от атак. Рабочие используются для добычи золота. Вы можете настроить количество войск и рабочих с помощью ползунка.",
"ui_attack_ratio": "Соотношение атаки — Количество войск, которое будет использоваться при атаке. Вы можете изменить соотношение атаки с помощью ползунка.",
"ui_options": "Настройки",
"ui_options_desc": "Среди них можно найти следующие элементы:",
"option_pause": "Приостановить/Продолжить игру — Доступно только в режиме одиночной игры.",
"option_timer": "Таймер — Время, прошедшее с начала игры.",
"option_exit": "Кнопка выхода.",
"option_settings": "Настройки — Открыть меню настроек. В нём вы можете переключать альтернативный вид, тёмный режим, смайлики и взаимодействие левой кнопкой мыши.",
"radial_title": "Круговое меню",
"radial_desc": "Щелчок правой кнопкой мыши (нажатие на мобильном устройстве) открывает круговое меню. Из него можно:",
"radial_build": "Открыть меню строительства.",
"radial_info": "Открыть меню информации.",
"radial_boat": "Отправить лодку для атаки указанного места (доступно только при наличии доступа к воде).",
"radial_close": "Закрыть меню.",
"info_title": "Меню информации",
"info_enemy_desc": "Содержит информацию, такую как имя выбранного игрока, золото, войска и метку предателя. Предатель — это игрок, который предал и напал на игрока, вступившего в альянс с ним. Значки ниже обозначают следующие взаимодействия:",
"info_target": "Поместить метку цели на игрока, отметив его для всех союзников. Используется для координирования атак.",
"info_alliance": "Отправить запрос альянса игроку. Союзники могут обмениваться ресурсами и войсками, но не могут атаковать друг друга.",
"info_emoji": "Отправить смайлик игроку.",
"info_ally_panel": "Панель информации о союзнике",
"info_ally_desc": "Когда вы заключите альянс с игроком, станут доступны следующие значки:",
"ally_betray": "Предайте своего союзника, разорвав альянс. Рядом с вашим именем появится постоянный значок. Боты будут с меньшей вероятностью заключать с вами альянс, а игроки подумают дважды, прежде чем сделать это.",
"ally_donate": "Пожертвовать часть войска союзнику. Используется, когда у него мало войск и его атакуют, или когда ему нужна дополнительная мощь для уничтожения врага.",
"build_menu_title": "Меню строительства",
"build_name": "Название",
"build_icon": "Значок",
"build_desc": "Описание",
"build_city": "Город",
"build_city_desc": "Увеличивает ваше максимальное населения. Полезно, когда вы не можете расширить свою территорию или скоро достигнете лимита населения.",
"build_defense": "Укрепление",
"build_defense_desc": "Повышает защиту вокруг ближайших границ. Атаки врагов замедлены и несут больше жертв.",
"build_port": "Порт",
"build_port_desc": "Автоматически отправляет торговые корабли между портами вашей страны и других стран (за исключением случаев, когда вы нажали «прекратить торговлю» на них или они нажали «прекратить торговлю» на вас), давая золото обеим сторонам. Позволяет строить военные корабли. Можно размещать только вблизи воды.",
"build_warship": "Военный корабль",
"build_warship_desc": "Патрулирует территорию, захватывая торговые корабли, а также разрушая вражеские военные корабли и лодки. Строиться в ближайшем порту и патрулирует территорию, выбранную нажатием кнопкой мыши.",
"build_silo": "Ракетная шахта",
"build_silo_desc": "Позволяет запускать ракеты.",
"build_sam": "Пусковая установка ЗРК",
"build_sam_desc": "Имеет 75% шанс перехвата снарядов противника в радиусе 100 пикселей. ЗРК имеет 7,5 секунды перезарядки и не может перехватить РГЧ ИН.",
"build_atom": "Атомная бомба",
"build_atom_desc": "Небольшая взрывная бомба, которая разрушает территорию, сооружения, корабли и лодки. Запускается из ближайшей ракетной шахты и наносит удар по области, выбранной нажатием кнопкой мыши.",
"build_hydrogen": "Водородная бомба",
"build_hydrogen_desc": "Большая взрывная бомба. Запускается из ближайшей ракетной шахты и наносит удар по области, выбранной нажатием кнопкой мыши.",
"build_mirv": "РГЧ ИН",
"build_mirv_desc": "Самая мощная бомба в игре. Разделяется на бомбы меньшего размера, которые покрывают огромную территорию. Наносит урон только выбранному игроку. Запускается из ближайшей ракетной шахты и наносит удар по области, выбранной нажатием кнопкой мыши.",
"player_icons": "Значки игрока",
"icon_desc": "Примеры некоторых иконок в игре, которые вы встретите и их значения:",
"icon_crown": "Корона — Это игрок номер 1 в таблице лидеров",
"icon_traitor": "Скрещённые мечи — Предатель. Этот игрок напал на союзника.",
"icon_ally": "Рукопожатие — Союзник. Этот игрок — ваш союзник.",
"info_enemy_panel": "Панель информации о враге"
},
"single_modal": {
"title": "Одиночная игра",
"allow_alliances": "Разрешить альянсы",
"options_title": "Настройки",
"bots": "Боты: ",
"bots_disabled": "Отключены",
"disable_nations": "Отключить нации",
"instant_build": "Мгновенная стройка",
"infinite_gold": "Неограниченное золото",
"infinite_troops": "Неограниченные войска",
"disable_nukes": "Отключить бомбы",
"start": "Начать игру"
},
"map": {
"world": "Мир",
"europe": "Европа",
"mena": "MENA",
"northamerica": "Северная Америка",
"oceania": "Океания",
"blacksea": "Чёрное море",
"africa": "Африка",
"asia": "Азия",
"mars": "Марс",
"southamerica": "Южная Америка",
"britannia": "Британия",
"gatewaytotheatlantic": "Гибралтарский пролив",
"australia": "Австралия",
"random": "Случайно",
"iceland": "Исландия",
"pangaea": "Пангея",
"map": "Карта",
"betweentwoseas": "Между двух морей",
"japanandneighbors": "Япония и соседи"
},
"private_lobby": {
"title": "Присоединиться к приватному лобби",
"enter_id": "Введите ID лобби",
"player": "Игрок",
"players": "Игрока(-ов)",
"join_lobby": "Присоединиться к лобби",
"checking": "Проверка лобби...",
"not_found": "Лобби не найдено. Пожалуйста, проверьте правильность ID и попробуйте ещё раз.",
"error": "Произошла ошибка. Пожалуйста, попробуйте ещё раз.",
"joined_waiting": "Вы успешно присоединились! Ожидание начала игры..."
},
"public_lobby": {
"join": "Присоединиться к следующей игре",
"waiting": "игрока(-ов) в ожидании"
},
"username": {
"enter_username": "Введите своё имя игрока",
"not_string": "Имя игрока должно быть строкой.",
"too_short": "Имя игрока должно содержать не менее {min} символов.",
"too_long": "Имя игрока не должно превышать {max} символов.",
"invalid_chars": "Имя игрока может содержать только латинские буквы, цифры, пробелы, подчёркивания и [квадратные скобки]."
},
"host_modal": {
"title": "Приватное лобби",
"options_title": "Настройки",
"bots": "Боты: ",
"bots_disabled": "Отключены",
"disable_nations": "Отключить нации",
"instant_build": "Мгновенная стройка",
"infinite_gold": "Неограниченное золото",
"infinite_troops": "Неограниченные войска",
"disable_nukes": "Отключить бомбы",
"player": "Игрок",
"players": "Игрока(-ов)",
"waiting": "Ожидание игроков...",
"start": "Начать игру",
"mode": "Режим"
},
"difficulty": {
"Relaxed": "Расслабленная",
"Balanced": "Уравновешенная",
"Intense": "Напряжённая",
"Impossible": "Невозможная",
"difficulty": "Сложность"
},
"game_starting_modal": {
"title": "Игра начинается...",
"desc": "Подготовка к запуску лобби. Пожалуйста, подождите."
},
"lang": {
"en": "Russian",
"native": "Русский",
"svg": "ru",
"lang_code": "ru"
},
"game_mode": {
"ffa": "Свободная игра (FFA)",
"teams": "Команды"
}
}
+175
View File
@@ -0,0 +1,175 @@
{
"main": {
"join_discord": "Приєднуйтеся до Discord!",
"create_lobby": "Створити лобі",
"join_lobby": "Приєднатися до лобі",
"single_player": "Гра наодинці",
"instructions": "Інструкції",
"how_to_play": "Як грати",
"wiki": "Вікі"
},
"help_modal": {
"hotkeys": "Гарячі клавіші",
"table_key": "Клавіша",
"table_action": "Дія",
"action_alt_view": "Альтернативний вигляд (ландшафт/країни)",
"action_attack_altclick": "Атака (коли клацання лівою кнопкою миші призначено на відкриття меню)",
"action_build": "Відкрити меню будівництва",
"action_center": "Відцентрувати камеру на гравцеві",
"action_zoom": "Віддалити/Приблизити",
"action_move_camera": "Перемістити камеру",
"action_ratio_change": "Зменшити/Збільшити співвідношення атаки",
"action_reset_gfx": "Скинути графіку",
"ui_section": "Ігровий інтерфейс",
"ui_leaderboard": "Таблиця лідерів",
"ui_leaderboard_desc": "Показує найкращих гравців та їх імена, % підконтрольних земель та кількість золота.",
"ui_control": "Панель керування",
"ui_control_desc": "Панель керування містить наступні елементи:",
"ui_pop": "Населення — Кількість ваших підрозділів, максимальне населення та темп його приросту.",
"ui_gold": "Золото — Обсяг вашого золота та швидкість, з якою ви отримуєте його.",
"ui_troops_workers": "Війська та Робітники — Кількість призначених військ і робітників. Війська використовуються для атаки або захисту від атак. Робітники використовуються для видобування золота. Ви можете регулювати кількість військ і робітників використовуючи повзунок.",
"ui_attack_ratio": "Співвідношення атаки — Кількість військ, що використовуватиметься під час атаки. Ви можете відрегулювати співвідношення атаки використовуючи повзунок.",
"ui_options": "Налаштування",
"ui_options_desc": "Серед них можна знайти наступні елементи:",
"option_pause": "Призупинити/Продовжити гру — доступно лише в режимі гри наодинці.",
"option_timer": "Таймер — Час, що минув із початку гри.",
"option_exit": "Кнопка виходу.",
"option_settings": "Налаштування — Відкрити меню налаштувань. В ньому можна перемкнути режим альтернативного вигляду, темний режим, емодзі та виконання дії при клацанні лівою кнопкою миші.",
"radial_title": "Кругове меню",
"radial_desc": "Правий клац (або дотик на мобільному пристрої) відкриває кругове меню. В ньому ви можете:",
"radial_build": "Відкрити меню будівництва.",
"radial_info": "Відкрити меню інформації.",
"radial_boat": "Надіслати човен для атаки вибраного місця (доступно лише якщо ви маєте доступ до води).",
"radial_close": "Закрити меню.",
"info_title": "Меню інформації",
"info_enemy_desc": "Містить таку інформацію, як ім'я вибраного гравця, кількість золота, війська та мітку зрадника. Зрадник — це гравець, що зрадив та атакував гравця, який перебував у альянсі з ними. Значки нижче позначають наступні взаємодії:",
"info_target": "Розмістити мітку цілі на гравці, позначивши його для всіх союзників. Використовується для координації атак.",
"info_alliance": "Надіслати гравцю запит на альянс. Союзники можуть ділитися ресурсами та військами, але не можуть атакувати один одного.",
"info_emoji": "Відправити емодзі гравцю.",
"info_ally_panel": "Панель інформації союзника",
"info_ally_desc": "Коли ви укладете альянс із гравцем, стануть доступними наступні значки:",
"ally_betray": "Зрадити союзника, розірвавши альянс. Ви отримаєте постійний значок поруч із вашим іменем. Боти рідше укладатимуть із вами альянси, а гравці подумають двічі, перш ніж робити це.",
"ally_donate": "Пожертвувати частину своїх військ союзнику. Використовується, коли в нього мало військ і його атакують, або коли йому необхідна додаткова сила для знищення ворога.",
"build_menu_title": "Меню будівництва",
"build_name": "Назва",
"build_icon": "Значок",
"build_desc": "Опис",
"build_city": "Місто",
"build_city_desc": "Збільшує вашу максимальну кількість населення. Може бути корисним, коли ви не можете розширити свою територію, або незабаром досягнете ліміту населення.",
"build_defense": "Пункт оборони",
"build_defense_desc": "Збільшує захист навколо найближчих кордонів. Атаки ворогів уповільнені й несуть більше жертв.",
"build_port": "Порт",
"build_port_desc": "Автоматично відправляє торгові кораблі між портами вашої країни та іншими країнами (за винятком випадків, коли ви натиснули «припинити торгівлю» на них або вони натиснули кнопку «припинити торгівлю» на вас), даючи золото обом сторонам. Дозволяє будувати військові кораблі. Можна розміщати тільки біля води.",
"build_warship": "Військовий корабель",
"build_warship_desc": "Патрулює територію, захоплюючи торгові кораблі та знищуючи ворожі кораблі й човни. Будується в найближчому порту й патрулює територію, вибрану клацанням кнопкою миші.",
"build_silo": "Ракетна шахта",
"build_silo_desc": "Дає можливість запускати ракети.",
"build_sam": "Пускова установка ЗРК",
"build_sam_desc": "Має шанс 75% перехопити ворожі ракети в радіусі 100 пікселів. ЗРК має 7,5 секунди перезарядження та не може перехопити РГЧ ІН.",
"build_atom": "Атомна бомба",
"build_atom_desc": "Невелика вибухова бомба, яка руйнує територію, будівлі, кораблі та човни. Запускається з найближчої ракетної шахти та вражає область, вибрану клацанням кнопкою миші.",
"build_hydrogen": "Воднева бомба",
"build_hydrogen_desc": "Велика вибухова бомба. Запускається з найближчої ракетної шахти та вражає область, вибрану клацанням кнопкою миші.",
"build_mirv": "РГЧ ІН",
"build_mirv_desc": "Найпотужніша бомба в грі. Розділяється на менші бомби, які покривають величезну територію. Завдає шкоду лише вибраному гравцю. Запускається з найближчої ракетної шахти та вражає область, вибрану клацанням кнопкою миші.",
"player_icons": "Значки гравця",
"icon_desc": "Приклади деяких ікон, з якими ви зіткнетесь, і їх значення:",
"icon_crown": "Корона — Це гравець номер 1 у таблиці лідерів",
"icon_traitor": "Перехрещені мечі — Зрадник. Цей гравець атакував союзника.",
"icon_ally": "Рукостискання — Союзник. Цей гравець є вашим союзником.",
"info_enemy_panel": "Панель інформації ворога"
},
"single_modal": {
"title": "Гра наодинці",
"allow_alliances": "Дозволити альянси",
"options_title": "Налаштування",
"bots": "Боти: ",
"bots_disabled": "Відключено",
"disable_nations": "Відключити нації",
"instant_build": "Миттєве будівництво",
"infinite_gold": "Нескінченне золото",
"infinite_troops": "Нескінченні війська",
"disable_nukes": "Відключити бомби",
"start": "Розпочати гру"
},
"map": {
"world": "Світ",
"europe": "Європа",
"mena": "MENA",
"northamerica": "Північна Америка",
"oceania": "Океанія",
"blacksea": "Чорне море",
"africa": "Африка",
"asia": "Азія",
"mars": "Марс",
"southamerica": "Південна Америка",
"britannia": "Британія",
"gatewaytotheatlantic": "Гібралтарська протока",
"australia": "Австралія",
"random": "Випадково",
"iceland": "Ісландія",
"pangaea": "Пангея",
"map": "Мапа",
"betweentwoseas": "Поміж двох морів",
"japanandneighbors": "Японія та сусіди"
},
"private_lobby": {
"title": "Приєднатися до приватного лобі",
"enter_id": "Введіть ID лобі",
"player": "Гравець",
"players": "Гравці(в)",
"join_lobby": "Приєднатися до лобі",
"checking": "Перевірка лобі...",
"not_found": "Лобі не знайдено. Будь ласка, перевірте дійсність ID і спробуйте знову.",
"error": "Сталася помилка. Будь ласка, спробуйте знову.",
"joined_waiting": "Ви успішно приєдналися! Очікування початку гри..."
},
"public_lobby": {
"join": "Приєднатися до наступної гри",
"waiting": "гравці(в) в очікуванні"
},
"username": {
"enter_username": "Введіть своє ім'я гравця",
"not_string": "Ім'я гравця має бути рядком.",
"too_short": "Ім'я гравця повинно містити щонайменше {min} символів.",
"too_long": "Ім'я гравця не повинно перевищувати {max} символів.",
"invalid_chars": "Ім'я гравця може містити лише латинські літери, цифри, пробіли, знаки підкреслення й [квадратні дужки]."
},
"host_modal": {
"title": "Приватне лобі",
"options_title": "Налаштування",
"bots": "Боти: ",
"bots_disabled": "Відключено",
"disable_nations": "Відключити нації",
"instant_build": "Миттєве будівництво",
"infinite_gold": "Нескінченне золото",
"infinite_troops": "Нескінченні війська",
"disable_nukes": "Відключити бомби",
"player": "Гравець",
"players": "Гравці(в)",
"waiting": "Очікування гравців...",
"start": "Розпочати гру",
"mode": "Режим"
},
"difficulty": {
"Relaxed": "Розслаблена",
"Balanced": "Збалансована",
"Intense": "Напружена",
"Impossible": "Неможлива",
"difficulty": "Складність"
},
"game_starting_modal": {
"title": "Гра починається...",
"desc": "Підготовка запуску лобі. Будь ласка, зачекайте."
},
"lang": {
"en": "Ukrainian",
"native": "Українська",
"svg": "ua",
"lang_code": "uk"
},
"game_mode": {
"ffa": "Вільна гра (FFA)",
"teams": "Команди"
}
}
+249 -167
View File
@@ -1,5 +1,6 @@
import { LitElement, html } from "lit"; import { LitElement, html } from "lit";
import { customElement, query } from "lit/decorators.js"; import { customElement, query } from "lit/decorators.js";
import { translateText } from "../client/Utils";
import "./components/Difficulties"; import "./components/Difficulties";
import "./components/Maps"; import "./components/Maps";
@@ -16,262 +17,343 @@ export class HelpModal extends LitElement {
render() { render() {
return html` return html`
<o-modal id="helpModal" title="Instructions" translationKey="main.instructions"> <o-modal
id="helpModal"
title="Instructions"
translationKey="main.instructions"
>
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<div data-i18n="help_modal.hotkeys" class="text-center text-2xl font-bold mb-4">Hotkeys</div> <div class="text-center text-2xl font-bold mb-4">
${translateText("help_modal.hotkeys")}
</div>
<table> <table>
<thead> <thead>
<tr> <tr>
<th data-i18n="help_modal.table_key">Key</th> <th>${translateText("help_modal.table_key")}</th>
<th data-i18n="help_modal.table_action">Action</th> <th>${translateText("help_modal.table_action")}</th>
</tr> </tr>
</thead> </thead>
<tbody class="text-left"> <tbody class="text-left">
<tr> <tr>
<td>Space</td> <td>Space</td>
<td data-i18n="help_modal.action_alt_view">Alternate view (terrain/countries)</td> <td>${translateText("help_modal.action_alt_view")}</td>
</tr> </tr>
<tr> <tr>
<td>Shift + left click</td> <td>Shift + left click</td>
<td data-i18n="help_modal.action_attack_altclick">Attack (when left click is set to open menu)</td> <td>${translateText("help_modal.action_attack_altclick")}</td>
</tr> </tr>
<tr> <tr>
<td>Ctrl + left click</td> <td>Ctrl + left click</td>
<td data-i18n="help_modal.action_build">Open build menu</td> <td>${translateText("help_modal.action_build")}</td>
</tr> </tr>
<tr> <tr>
<td>C</td> <td>C</td>
<td data-i18n="help_modal.action_center">Center camera on player</td> <td>${translateText("help_modal.action_center")}</td>
</tr> </tr>
<tr> <tr>
<td>Q / E</td> <td>Q / E</td>
<td data-i18n="help_modal.action_zoom">Zoom out/in</td> <td>${translateText("help_modal.action_zoom")}</td>
</tr> </tr>
<tr> <tr>
<td>W / A / S / D</td> <td>W / A / S / D</td>
<td data-i18n="help_modal.action_move_camera">Move camera</td> <td>${translateText("help_modal.action_move_camera")}</td>
</tr> </tr>
<tr> <tr>
<td>1 / 2</td> <td>1 / 2</td>
<td data-i18n="help_modal.action_ratio_change">Decrease/Increase attack ratio</td> <td>${translateText("help_modal.action_ratio_change")}</td>
</tr> </tr>
<tr> <tr>
<td>Shift + scroll down / scroll up</td> <td>Shift + scroll down / scroll up</td>
<td data-i18n="help_modal.action_ratio_change">Decrease/Increase attack ratio</td> <td>${translateText("help_modal.action_ratio_change")}</td>
</tr> </tr>
<tr> <tr>
<td>ALT + R</td> <td>ALT + R</td>
<td data-i18n="help_modal.action_reset_gfx">Reset graphics</td> <td>${translateText("help_modal.action_reset_gfx")}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<hr class="mt-6 mb-4"> <hr class="mt-6 mb-4" />
<div data-i18n="help_modal.ui_section" class="text-2xl font-bold text-center mb-4">Game UI</div> <div class="text-2xl font-bold text-center mb-4">
${translateText("help_modal.ui_section")}
</div>
<div class="flex flex-col md:flex-row gap-4"> <div class="flex flex-col md:flex-row gap-4">
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<div data-i18n="help_modal.ui_leaderboard" class="text-gray-300">Leaderboard</div> <div class="text-gray-300">
<img src="/images/helpModal/leaderboard.webp" alt="Leaderboard" title="Leaderboard" /> ${translateText("help_modal.ui_leaderboard")}
</div>
<img
src="/images/helpModal/leaderboard.webp"
alt="Leaderboard"
title="Leaderboard"
/>
</div> </div>
<div> <div>
<p data-i18n="help_modal.ui_leaderboard_desc">Shows the top players of the game and their names, % owned land and gold.</p> <p>${translateText("help_modal.ui_leaderboard_desc")}</p>
</div> </div>
</div> </div>
<hr class="mt-6 mb-4"> <hr class="mt-6 mb-4" />
<div class="flex flex-col md:flex-row gap-4"> <div class="flex flex-col md:flex-row gap-4">
<div class="flex flex-col items-center w-full md:w-[80%]"> <div class="flex flex-col items-center w-full md:w-[80%]">
<div data-i18n="help_modal.ui_control" class="text-gray-300">Control panel</div> <div class="text-gray-300">
<img src="/images/helpModal/controlPanel.webp" alt="Control panel" title="Control panel" /> ${translateText("help_modal.ui_control")}
</div>
<img
src="/images/helpModal/controlPanel.webp"
alt="Control panel"
title="Control panel"
/>
</div> </div>
<div> <div>
<p data-i18n="help_modal.ui_control_desc" class="mb-4">The control panel contains the following elements:</p> <p class="mb-4">${translateText("help_modal.ui_control_desc")}</p>
<ul> <ul>
<li data-i18n="help_modal.ui_pop" class="mb-4">Pop - The amount of units you have, your max population and the rate at which you gain them.</li> <li class="mb-4">${translateText("help_modal.ui_pop")}</li>
<li data-i18n="help_modal.ui_gold" class="mb-4">Gold - The amount of gold you have and the rate at which you gain it.</li> <li class="mb-4">${translateText("help_modal.ui_gold")}</li>
<li data-i18n="help_modal.ui_troops_workers" class="mb-4">Troops and Workers - The amount of allocated troops and workers. Troops are used to attack or defend against attacks. Workers are used to generate gold. You can adjust the number of troops and workers using the slider.</li> <li class="mb-4">
<li data-i18n="help_modal.ui_attack_ratio" class="mb-4">Attack ratio - The amount of troops that will be used when you attack. You can adjust the attack ratio using the slider.</li> ${translateText("help_modal.ui_troops_workers")}
</li>
<li class="mb-4">
${translateText("help_modal.ui_attack_ratio")}
</li>
</ul> </ul>
</div> </div>
</div> </div>
<hr class="mt-6 mb-4"> <hr class="mt-6 mb-4" />
<div class="flex flex-col md:flex-row gap-4"> <div class="flex flex-col md:flex-row gap-4">
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<div data-i18n="help_modal.ui_options" class="text-gray-300">Options</div> <div class="text-gray-300">
<img src="/images/helpModal/options.webp" alt="Options" title="Options" /> ${translateText("help_modal.ui_options")}
</div>
<img
src="/images/helpModal/options.webp"
alt="Options"
title="Options"
/>
</div> </div>
<div> <div>
<p data-i18n="help_modal.ui_options_desc" class="mb-4">The following elements can be found inside:</p> <p class="mb-4">${translateText("help_modal.ui_options_desc")}</p>
<ul> <ul>
<li data-i18n="help_modal.option_pause" class="mb-4">Pause/Unpause the game - Only available in single player mode.</li> <li class="mb-4">${translateText("help_modal.option_pause")}</li>
<li data-i18n="help_modal.option_timer" class="mb-4">Timer - Time passed since the start of the game.</li> <li class="mb-4">${translateText("help_modal.option_timer")}</li>
<li data-i18n="help_modal.option_exit" class="mb-4">Exit button.</li> <li class="mb-4">${translateText("help_modal.option_exit")}</li>
<li data-i18n="help_modal.option_settings" class="mb-4">Settings - Open the settings menu. Inside you can toggle the Alternate View, Dark Mode, Emojis and action on left click.</li> <li class="mb-4">
${translateText("help_modal.option_settings")}
</li>
</ul> </ul>
</div> </div>
</div> </div>
<hr class="mt-6 mb-4"> <hr class="mt-6 mb-4" />
<div data-i18n="radial_title" class="text-2xl font-bold text-center">Radial menu</div> <div class="text-2xl font-bold text-center">
${translateText("help_modal.radial_title")}
</div>
<div class="flex flex-col md:flex-row gap-4"> <div class="flex flex-col md:flex-row gap-4">
<img src="/images/helpModal/radialMenu.webp" alt="Radial menu" title="Radial menu", class="radial-menu-image" /> <img
src="/images/helpModal/radialMenu.webp"
alt="Radial menu"
title="Radial menu"
,
class="radial-menu-image"
/>
<div> <div>
<p data-i18n="help_modal.radial_desc" class="mb-4">Right clicking (or touch on mobile) opens the radial menu. From there you can:</p> <p class="mb-4">${translateText("help_modal.radial_desc")}</p>
<ul> <ul>
<li class="mb-4"><div class="inline-block icon build-icon"></div><span data-i18n="help_modal.radial_build"> - Open the build menu.</span></li>
<li class="mb-4"> <li class="mb-4">
<img src="/images/InfoIcon.svg" class="inline-block icon" style="fill: white; background: transparent;"/><span data-i18n="help_modal.radial_info"> - Open the Info menu.</span></li> <div class="inline-block icon build-icon"></div>
<li class="mb-4"><div class="inline-block icon boat-icon"></div><span data-i18n="help_modal.radial_boat"> - Send a boat to attack at the selected location (only available if you have access to water).</span></li> <span>${translateText("help_modal.radial_build")}</span>
<li class="mb-4"><div class="inline-block icon cancel-icon"></div><span data-i18n="help_modal.radial_close"> - Close the menu.</span></li> </li>
<li class="mb-4">
<img
src="/images/InfoIcon.svg"
class="inline-block icon"
style="fill: white; background: transparent;"
/>
<span>${translateText("help_modal.radial_info")}</span>
</li>
<li class="mb-4">
<div class="inline-block icon boat-icon"></div>
<span>${translateText("help_modal.radial_boat")}</span>
</li>
<li class="mb-4">
<div class="inline-block icon cancel-icon"></div>
<span>${translateText("help_modal.radial_close")}</span>
</li>
</ul> </ul>
</div> </div>
</div> </div>
<hr class="mt-6 mb-4"> <hr class="mt-6 mb-4" />
<div> <div>
<div data-i18n="help_modal.info_title" class="text-2xl font-bold text-center">Info menu</div> <div class="text-2xl font-bold text-center">
${translateText("help_modal.info_title")}
</div>
<div class="flex flex-col md:flex-row gap-4 mt-2"> <div class="flex flex-col md:flex-row gap-4 mt-2">
<div class="flex flex-col items-center w-full md:w-[80%]"> <div class="flex flex-col items-center w-full md:w-[80%]">
<div data-i18n="help_modal.info_enemy_panel" class="text-gray-300">Enemy info panel</div> <divclass="text-gray-300">
<img src="/images/helpModal/infoMenu.webp" alt="Enemy info panel" title="Enemy info panel" /> ${translateText("help_modal.info_enemy_panel")}
</div>
<img
src="/images/helpModal/infoMenu.webp"
alt="Enemy info panel"
title="Enemy info panel"
/>
</div> </div>
<div class="pt-4"> <div class="pt-4">
<p data-i18n="help_modal.info_enemy_desc" class="mb-4"> <p class="mb-4">${translateText("help_modal.info_enemy_desc")}</p>
Contains information such for the selected player name, gold, troops, and if the player is a traitor. Traitor is a player who betrayed and attacked a player who was in an alliance with them. The icons below represent the following interactions:
</p>
<ul> <ul>
<li class="mb-4"><div class="inline-block icon target-icon"></div><span data-i18n="help_modal.info_target"> - Place a target mark on the player, marking it for all allies, used to coordinate attacks.</span></li> <li class="mb-4">
<li class="mb-4"><div class="inline-block icon alliance-icon"></div><span data-i18n="help_modal.info_alliance"> - Send an alliance request to the player. Allies can share resources and troops, but can't attack each other.</span></li> <div class="inline-block icon target-icon"></div>
<li><div class="inline-block icon emoji-icon"></div><span data-i18n="help_modal.info_emoji"> - Send an emoji to the player.</span></li> <span>${translateText("help_modal.info_target")}</span>
</li>
<li class="mb-4">
<div class="inline-block icon alliance-icon"></div>
<span>${translateText("help_modal.info_alliance")}</span>
</li>
<li>
<div class="inline-block icon emoji-icon"></div>
<span>${translateText("help_modal.info_emoji")}</span>
</li>
</ul> </ul>
</div> </div>
</div> </div>
<hr class="mt-6 mb-4"> <hr class="mt-6 mb-4" />
<div class="flex flex-col md:flex-row gap-4"> <div class="flex flex-col md:flex-row gap-4">
<div class="flex flex-col items-center w-full md:w-[62%]"> <div class="flex flex-col items-center w-full md:w-[62%]">
<div data-i18n="help_modal.info_ally_panel" class="text-gray-300">Ally info panel</div> <div class="text-gray-300">
<img src="/images/helpModal/infoMenuAlly.webp" alt="Ally info panel" title="Ally info panel" /> ${translateText("help_modal.info_ally_panel")}
</div>
<img
src="/images/helpModal/infoMenuAlly.webp"
alt="Ally info panel"
title="Ally info panel"
/>
</div> </div>
<div class="pt-4"> <div class="pt-4">
<p data-i18n="help_modal.info_ally_desc" class="mb-4"> <p class="mb-4">${translateText("help_modal.info_ally_desc")}</p>
When you ally with a player, the following new icons become available:
</p>
<ul> <ul>
<li class="mb-4"><div class="inline-block icon betray-icon"></div><span data-i18n="help_modal.ally_betray"> - Betray your ally, ending the alliance. You will now have a permanent icon stuck next to your name. Bots are less likely to ally with you and players will think twice before doing so.</span></li> <li class="mb-4">
<li class="mb-4"><div class="inline-block icon donate-icon"></div><span data-i18n="help_modal.ally_donate"> - Donate some of your troops to your ally. Used when they're low on troops and are being attacked, or when they need that extra power to crush an enemy.</span></li> <div class="inline-block icon betray-icon"></div>
<span>${translateText("help_modal.ally_betray")}</span>
</li>
<li class="mb-4">
<div class="inline-block icon donate-icon"></div>
<span>${translateText("help_modal.ally_donate")}</span>
</li>
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
<hr class="mt-6 mb-4"> <hr class="mt-6 mb-4" />
<div> <div>
<div data-i18n="help_modal.build_menu_title" class="text-2xl font-bold mb-4 text-center">Build menu</div> <div class="text-2xl font-bold mb-4 text-center">
${translateText("help_modal.build_menu_title")}
</div>
<table> <table>
<thead> <thead>
<tr> <tr>
<th data-i18n="help_modal.build_name">Name</th> <th>${translateText("help_modal.build_name")}</th>
<th data-i18n="help_modal.build_icon">Icon</th> <th>${translateText("help_modal.build_icon")}</th>
<th data-i18n="help_modal.build_desc">Description</th> <th>${translateText("help_modal.build_desc")}</th>
</tr> </tr>
</thead> </thead>
<tbody class="text-left"> <tbody class="text-left">
<tr> <tr>
<td data-i18n="help_modal.build_city">City</td> <td>${translateText("help_modal.build_city")}</td>
<td><div class="icon city-icon"></div></td> <td><div class="icon city-icon"></div></td>
<td data-i18n="help_modal.build_city_desc"> <td>${translateText("help_modal.build_city_desc")}</td>
Increases your max population. Useful when you can't </tr>
expand your territory or you're about to hit your <tr>
population limit. <td>${translateText("help_modal.build_defense")}</td>
</td> <td><div class="icon defense-post-icon"></div></td>
</tr> <td>${translateText("help_modal.build_defense_desc")}</td>
<tr> </tr>
<td data-i18n="help_modal.build_defense">Defense Post</td> <tr>
<td><div class="icon defense-post-icon"></div></td> <td>${translateText("help_modal.build_port")}</td>
<td data-i18n="help_modal.build_defense_desc"> <td><div class="icon port-icon"></div></td>
Increases defenses around nearby borders. Attacks from <td>${translateText("help_modal.build_port_desc")}</td>
enemies are slower and have more casualties. </tr>
</td> <tr>
</tr> <td>${translateText("help_modal.build_warship")}</td>
<tr> <td><div class="icon warship-icon"></div></td>
<td data-i18n="help_modal.build_port">Port</td> <td>${translateText("help_modal.build_warship_desc")}</td>
<td><div class="icon port-icon"></div></td> </tr>
<td data-i18n="help_modal.build_port_desc"> <tr>
Automatically sends trade ships between ports of your <td>${translateText("help_modal.build_silo")}</td>
country and other countries (except if you clicked "stop <td><div class="icon missile-silo-icon"></div></td>
trade" on them or they clicked "stop trade on you"), giving <td>${translateText("help_modal.build_silo_desc")}</td>
gold to both sides. Allows building Battleships. Can only </tr>
be built near water. <tr>
</td> <td>${translateText("help_modal.build_sam")}</td>
</tr> <td><div class="icon sam-launcher-icon"></div></td>
<tr> <td>${translateText("help_modal.build_sam_desc")}</td>
<td data-i18n="help_modal.build_warship">Warship</td> </tr>
<td><div class="icon warship-icon"></div></td> <tr>
<td data-i18n="help_modal.build_warship_desc"> <td>${translateText("help_modal.build_atom")}</td>
Patrols in an area, capturing trade ships and destroying <td><div class="icon atom-bomb-icon"></div></td>
enemy Warships and Boats. Spawns from the nearest Port and <td>${translateText("help_modal.build_atom_desc")}</td>
patrols the area you first clicked to build it. </tr>
</td> <tr>
</tr> <td>${translateText("help_modal.build_hydrogen")}</td>
<tr> <td><div class="icon hydrogen-bomb-icon"></div></td>
<td data-i18n="help_modal.build_silo">Missile Silo</td> <td>${translateText("help_modal.build_hydrogen_desc")}</td>
<td><div class="icon missile-silo-icon"></div></td> </tr>
<td data-i18n="help_modal.build_silo_desc">Allows launching missiles.</td> <tr>
</tr> <td>${translateText("help_modal.build_mirv")}</td>
<tr> <td><div class="icon mirv-icon"></div></td>
<td data-i18n="help_modal.build_sam">SAM Launcher</td> <td>${translateText("help_modal.build_mirv_desc")}</td>
<td><div class="icon sam-launcher-icon"></div></td> </tr>
<td data-i18n="help_modal.build_sam_desc">Has a 75% chance to intercept enemy missiles in it's 100 pixel range.
The SAM has a 7.5 second cooldown and can not intercept MIRVs.</td>
</tr>
<tr>
<td data-i18n="help_modal.build_atom">Atom Bomb</td>
<td><div class="icon atom-bomb-icon"></div></td></td>
<td data-i18n="help_modal.build_atom_desc">Small explosive bomb that destroys territory, buildings, ships and boats. Spawns from the nearest Missile Silo and lands in the area you first clicked to build it.</td>
</tr>
<tr>
<td data-i18n="help_modal.build_hydrogen">Hydrogen Bomb</td>
<td><div class="icon hydrogen-bomb-icon"></div></td></td>
<td data-i18n="help_modal.build_hydrogen_desc">Large explosive bomb. Spawns from the nearest Missile Silo and lands in the area you first clicked to build it.</td>
</tr>
<tr>
<td data-i18n="help_modal.build_mirv">MIRV</td>
<td><div class="icon mirv-icon"></div></td>
<td data-i18n="help_modal.build_mirv_desc">The most powerful bomb in the game. Splits up into smaller bombs that will cover a huge range of territory. Only damages the player that you first clicked on to build it. Spawns from the nearest Missile Silo and lands in the area you first clicked to build it.</td>
</tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<hr class="mt-6 mb-4"> <hr class="mt-6 mb-4" />
<div> <div>
<div data-i18n="help_modal.player_icons" class="text-2xl font-bold text-center">Player icons</div> <div class="text-2xl font-bold text-center">
<p data-i18n="help_modal.icon_desc">Examples of some of the ingame icons you will encounter and what they mean:</p> ${translateText("help_modal.player_icons")}
</div>
<p>${translateText("help_modal.icon_desc")}</p>
<div class="flex flex-col md:flex-row gap-4 mt-2"> <div class="flex flex-col md:flex-row gap-4 mt-2">
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<div data-i18n="help_modal.icon_crown" class="text-gray-300">Crown - This is the number 1 player in the leaderboard</div> <div class="text-gray-300">
<img src="/images/helpModal/number1.webp" alt="Number 1 player" title="Number 1 player" /> ${translateText("help_modal.icon_crown")}
</div>
<img
src="/images/helpModal/number1.webp"
alt="Number 1 player"
title="Number 1 player"
/>
</div> </div>
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<div data-i18n="help_modal.icon_traitor" class="text-gray-300">Crossed swords - Traitor. This player attacked an ally.</div> <div class="text-gray-300">
<img src="/images/helpModal/traitor.webp" alt="Traitor" title="Traitor" /> ${translateText("help_modal.icon_traitor")}
</div>
<img
src="/images/helpModal/traitor.webp"
alt="Traitor"
title="Traitor"
/>
</div> </div>
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<div data-i18n="help_modal.icon_ally" class="text-gray-300">Handshake - Ally. This player is your ally.</div> <div class="text-gray-300">
${translateText("help_modal.icon_ally")}
</div>
<img src="/images/helpModal/ally.webp" alt="Ally" title="Ally" /> <img src="/images/helpModal/ally.webp" alt="Ally" title="Ally" />
</div> </div>
</div> </div>
+12 -12
View File
@@ -72,7 +72,7 @@ export class HostLobbyModal extends LitElement {
<div class="options-layout"> <div class="options-layout">
<!-- Map Selection --> <!-- Map Selection -->
<div class="options-section"> <div class="options-section">
<div class="option-title">${translateText("host_modal.map")}</div> <div class="option-title">${translateText("map.map")}</div>
<div class="option-cards"> <div class="option-cards">
${Object.entries(GameMapType) ${Object.entries(GameMapType)
.filter(([key]) => isNaN(Number(key))) .filter(([key]) => isNaN(Number(key)))
@@ -110,7 +110,7 @@ export class HostLobbyModal extends LitElement {
<!-- Difficulty Selection --> <!-- Difficulty Selection -->
<div class="options-section"> <div class="options-section">
<div class="option-title">${translateText("host_modal.difficulty")}</div> <div class="option-title">${translateText("difficulty.difficulty")}</div>
<div class="option-cards"> <div class="option-cards">
${Object.entries(Difficulty) ${Object.entries(Difficulty)
.filter(([key]) => isNaN(Number(key))) .filter(([key]) => isNaN(Number(key)))
@@ -186,13 +186,13 @@ export class HostLobbyModal extends LitElement {
</label> </label>
<label <label
for="host-modal-disable-npcs" for="disable-npcs"
class="option-card ${this.disableNPCs ? "selected" : ""}" class="option-card ${this.disableNPCs ? "selected" : ""}"
> >
<div class="checkbox-icon"></div> <div class="checkbox-icon"></div>
<input <input
type="checkbox" type="checkbox"
id="host-modal-disable-npcs" id="disable-npcs"
@change=${this.handleDisableNPCsChange} @change=${this.handleDisableNPCsChange}
.checked=${this.disableNPCs} .checked=${this.disableNPCs}
/> />
@@ -202,13 +202,13 @@ export class HostLobbyModal extends LitElement {
</label> </label>
<label <label
for="host-modal-instant-build" for="instant-build"
class="option-card ${this.instantBuild ? "selected" : ""}" class="option-card ${this.instantBuild ? "selected" : ""}"
> >
<div class="checkbox-icon"></div> <div class="checkbox-icon"></div>
<input <input
type="checkbox" type="checkbox"
id="host-modal-instant-build" id="instant-build"
@change=${this.handleInstantBuildChange} @change=${this.handleInstantBuildChange}
.checked=${this.instantBuild} .checked=${this.instantBuild}
/> />
@@ -218,13 +218,13 @@ export class HostLobbyModal extends LitElement {
</label> </label>
<label <label
for="host-modal-infinite-gold" for="infinite-gold"
class="option-card ${this.infiniteGold ? "selected" : ""}" class="option-card ${this.infiniteGold ? "selected" : ""}"
> >
<div class="checkbox-icon"></div> <div class="checkbox-icon"></div>
<input <input
type="checkbox" type="checkbox"
id="host-modal-infinite-gold" id="infinite-gold"
@change=${this.handleInfiniteGoldChange} @change=${this.handleInfiniteGoldChange}
.checked=${this.infiniteGold} .checked=${this.infiniteGold}
/> />
@@ -234,13 +234,13 @@ export class HostLobbyModal extends LitElement {
</label> </label>
<label <label
for="host-modal-infinite-troops" for="infinite-troops"
class="option-card ${this.infiniteTroops ? "selected" : ""}" class="option-card ${this.infiniteTroops ? "selected" : ""}"
> >
<div class="checkbox-icon"></div> <div class="checkbox-icon"></div>
<input <input
type="checkbox" type="checkbox"
id="host-modal-infinite-troops" id="infinite-troops"
@change=${this.handleInfiniteTroopsChange} @change=${this.handleInfiniteTroopsChange}
.checked=${this.infiniteTroops} .checked=${this.infiniteTroops}
/> />
@@ -250,13 +250,13 @@ export class HostLobbyModal extends LitElement {
</label> </label>
<label <label
for="host-modal-disable-nukes" for="disable-nukes"
class="option-card ${this.disableNukes ? "selected" : ""}" class="option-card ${this.disableNukes ? "selected" : ""}"
> >
<div class="checkbox-icon"></div> <div class="checkbox-icon"></div>
<input <input
type="checkbox" type="checkbox"
id="host-modal-disable-nukes" id="disable-nukes"
@change=${this.handleDisableNukesChange} @change=${this.handleDisableNukesChange}
.checked=${this.disableNukes} .checked=${this.disableNukes}
/> />
+197 -100
View File
@@ -1,42 +1,61 @@
import { LitElement, html } from "lit"; import { LitElement, html } from "lit";
import { customElement, state } from "lit/decorators.js"; import { customElement, state } from "lit/decorators.js";
import "./LanguageModal";
// Import language files import bg from "../../resources/lang/bg.json";
import bgTranslations from "../../resources/lang/bg.json"; import de from "../../resources/lang/de.json";
import deTranslations from "../../resources/lang/de.json"; import en from "../../resources/lang/en.json";
import enTranslations from "../../resources/lang/en.json"; import es from "../../resources/lang/es.json";
import esTranslations from "../../resources/lang/es.json"; import fr from "../../resources/lang/fr.json";
import frTranslations from "../../resources/lang/fr.json"; import ja from "../../resources/lang/ja.json";
import jaTranslations from "../../resources/lang/ja.json"; import nl from "../../resources/lang/nl.json";
import nlTranslations from "../../resources/lang/nl.json"; import pl from "../../resources/lang/pl.json";
import ru from "../../resources/lang/ru.json";
const translations = { import uk from "../../resources/lang/uk.json";
en: enTranslations,
bg: bgTranslations,
ja: jaTranslations,
fr: frTranslations,
nl: nlTranslations,
de: deTranslations,
es: esTranslations,
};
type Translation = Partial<(typeof translations)[keyof typeof translations]>;
@customElement("lang-selector") @customElement("lang-selector")
export class LangSelector extends LitElement { export class LangSelector extends LitElement {
@state() public translations: Translation = {}; @state() public translations: any = {};
@state() private defaultTranslations = {}; @state() private defaultTranslations: any = {};
@state() private currentLang: string = "en"; @state() private currentLang: string = "en";
@state() private languageList: any[] = [];
@state() private showModal: boolean = false;
@state() private debugMode: boolean = false;
private dKeyPressed: boolean = false;
private languageMap: Record<string, any> = {
bg,
de,
en,
es,
fr,
ja,
nl,
pl,
ru,
uk,
};
createRenderRoot() { createRenderRoot() {
return this; return this; // Use Light DOM if you prefer this
} }
connectedCallback() { connectedCallback() {
super.connectedCallback(); super.connectedCallback();
this.setupDebugKey();
this.initializeLanguage(); this.initializeLanguage();
} }
private setupDebugKey() {
window.addEventListener("keydown", (e) => {
if (e.key.toLowerCase() === "t") this.dKeyPressed = true;
});
window.addEventListener("keyup", (e) => {
if (e.key.toLowerCase() === "t") this.dKeyPressed = false;
});
}
private async initializeLanguage() { private async initializeLanguage() {
const locale = new Intl.Locale(navigator.language); const locale = new Intl.Locale(navigator.language);
const defaultLang = locale.language; const defaultLang = locale.language;
@@ -46,21 +65,86 @@ export class LangSelector extends LitElement {
this.translations = await this.loadLanguage(userLang); this.translations = await this.loadLanguage(userLang);
this.currentLang = userLang; this.currentLang = userLang;
this.applyTranslation(); await this.loadLanguageList();
this.applyTranslation(this.translations);
} }
private async loadLanguage(lang: string): Promise<Translation> { private async loadLanguage(lang: string): Promise<any> {
return Promise.resolve(this.languageMap[lang] || {});
}
private async loadLanguageList() {
try { try {
const translation = translations[lang as keyof typeof translations]; const data = this.languageMap;
if (!translation) throw new Error(`Language file not found: ${lang}`); let list: any[] = [];
return translation;
} catch (error) { const browserLang = new Intl.Locale(navigator.language).language;
console.error("🚨 Translation load error:", error);
return {}; for (const langCode of Object.keys(data)) {
const langData = data[langCode].lang;
if (!langData) continue;
list.push({
code: langData.lang_code ?? langCode,
native: langData.native ?? langCode,
en: langData.en ?? langCode,
svg: langData.svg ?? langCode,
});
}
let debugLang: any = null;
if (this.dKeyPressed) {
debugLang = {
code: "debug",
native: "Debug",
en: "Debug",
svg: "xx",
};
this.debugMode = true;
}
const currentLangEntry = list.find((l) => l.code === this.currentLang);
const browserLangEntry =
browserLang !== this.currentLang && browserLang !== "en"
? list.find((l) => l.code === browserLang)
: undefined;
const englishEntry =
this.currentLang !== "en"
? list.find((l) => l.code === "en")
: undefined;
list = list.filter(
(l) =>
l.code !== this.currentLang &&
l.code !== browserLang &&
l.code !== "en" &&
l.code !== "debug",
);
list.sort((a, b) => a.en.localeCompare(b.en));
const finalList: any[] = [];
if (currentLangEntry) finalList.push(currentLangEntry);
if (englishEntry) finalList.push(englishEntry);
if (browserLangEntry) finalList.push(browserLangEntry);
finalList.push(...list);
if (debugLang) finalList.push(debugLang);
this.languageList = finalList;
} catch (err) {
console.error("Failed to load language list:", err);
} }
} }
private applyTranslation() { private async changeLanguage(lang: string) {
localStorage.setItem("lang", lang);
this.translations = await this.loadLanguage(lang);
this.currentLang = lang;
this.applyTranslation(this.translations);
this.showModal = false;
}
private applyTranslation(translations: any) {
const components = [ const components = [
"single-player-modal", "single-player-modal",
"host-lobby-modal", "host-lobby-modal",
@@ -75,32 +159,44 @@ export class LangSelector extends LitElement {
"help-modal", "help-modal",
"username-input", "username-input",
"public-lobby", "public-lobby",
"o-modal",
"o-button",
]; ];
const main = this.translations.main; document.title = translations.main?.title || document.title;
if (main && "title" in main) {
document.title = main.title;
}
document.querySelectorAll("[data-i18n]").forEach((element) => { document.querySelectorAll("[data-i18n]").forEach((element) => {
const key = element.getAttribute("data-i18n"); const key = element.getAttribute("data-i18n");
const text = this.translateText(key); const keys = key?.split(".") || [];
let text = translations;
for (const k of keys) {
text = text?.[k];
if (!text) break;
}
if (!text && this.defaultTranslations) {
let fallback = this.defaultTranslations;
for (const k of keys) {
fallback = fallback?.[k];
if (!fallback) break;
}
text = fallback;
}
if (text) { if (text) {
element.innerHTML = text; element.innerHTML = text;
} else { } else {
console.warn(`Missing translation key: ${key}`); console.warn(`Translation key not found: ${key}`);
} }
}); });
components.forEach((tagName) => { components.forEach((tag) => {
const el = document.querySelector(tagName) as LitElement; document.querySelectorAll(tag).forEach((el) => {
if (el && typeof el.requestUpdate === "function") { if (typeof (el as any).requestUpdate === "function") {
el.requestUpdate(); (el as any).requestUpdate();
} else { }
console.warn( });
`requestUpdate() not available on <${tagName}> or element not found.`,
);
}
}); });
} }
@@ -109,13 +205,19 @@ export class LangSelector extends LitElement {
params: Record<string, string | number> = {}, params: Record<string, string | number> = {},
): string { ): string {
const keys = key.split("."); const keys = key.split(".");
let text = findTranslation(keys, this.translations); let text: any = this.translations;
if (!text && this.defaultTranslations) {
text = findTranslation(keys, this.defaultTranslations); for (const k of keys) {
text = text?.[k];
if (!text) break;
} }
if (text == null || typeof text !== "string") { if (!text && this.defaultTranslations) {
return null; text = this.defaultTranslations;
for (const k of keys) {
text = text?.[k];
if (!text) return key;
}
} }
for (const [param, value] of Object.entries(params)) { for (const [param, value] of Object.entries(params)) {
@@ -125,58 +227,53 @@ export class LangSelector extends LitElement {
return text; return text;
} }
private async changeLanguage(lang: string) { private openModal() {
localStorage.setItem("lang", lang); this.debugMode = this.dKeyPressed;
this.translations = await this.loadLanguage(lang); this.showModal = true;
this.currentLang = lang; this.loadLanguageList();
this.applyTranslation();
} }
render() { render() {
const currentLang =
this.languageList.find((l) => l.code === this.currentLang) ??
(this.currentLang === "debug"
? {
code: "debug",
native: "Debug",
en: "Debug",
svg: "xx",
}
: {
native: "English",
en: "English",
svg: "xx",
});
return html` return html`
<select <div class="container__row">
@change=${(e: Event) => <button
this.changeLanguage((e.target as HTMLSelectElement).value)} id="lang-selector"
class="text-center appearance-none w-full bg-blue-100 hover:bg-blue-200 text-blue-900 p-3 sm:p-4 lg:p-5 font-medium text-sm sm:text-base lg:text-lg rounded-md border-none cursor-pointer transition-colors duration-300" @click=${this.openModal}
> class="text-center appearance-none w-full bg-blue-100 hover:bg-blue-200 text-blue-900 p-3 sm:p-4 lg:p-5 font-medium text-sm sm:text-base lg:text-lg rounded-md border-none cursor-pointer transition-colors duration-300 flex items-center gap-2 justify-center"
<option value="en" ?selected=${this.currentLang === "en"}> >
English <img
</option> id="lang-flag"
<option value="bg" ?selected=${this.currentLang === "bg"}> class="w-6 h-4"
Български src="/flags/${currentLang.svg}.svg"
</option> alt="flag"
<option value="ja" ?selected=${this.currentLang === "ja"}> />
<span id="lang-name">${currentLang.native} (${currentLang.en})</span>
</option> </button>
<option value="fr" ?selected=${this.currentLang === "fr"}> </div>
Français
</option> <language-modal
<option value="nl" ?selected=${this.currentLang === "nl"}> .visible=${this.showModal}
Nederlands .languageList=${this.languageList}
</option> .currentLang=${this.currentLang}
<option value="de" ?selected=${this.currentLang === "de"}> @language-selected=${(e: CustomEvent) =>
Deutsch this.changeLanguage(e.detail.lang)}
</option> @close-modal=${() => (this.showModal = false)}
<option value="es" ?selected=${this.currentLang === "es"}> ></language-modal>
Español
</option>
</select>
`; `;
} }
} }
function findTranslation(
keys: string[],
translations: Translation,
): string | null {
let ptr: unknown = translations;
for (const k of keys) {
ptr = ptr?.[k];
if (!ptr) break;
}
if (ptr && typeof ptr === "string") {
return ptr;
} else {
return null;
}
}
+149
View File
@@ -0,0 +1,149 @@
import { LitElement, css, html } from "lit";
import { customElement, property } from "lit/decorators.js";
@customElement("language-modal")
export class LanguageModal extends LitElement {
@property({ type: Boolean }) visible = false;
@property({ type: Array }) languageList: any[] = [];
@property({ type: String }) currentLang = "en";
static styles = css`
.modal {
position: fixed;
inset: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 50;
display: flex;
justify-content: center;
align-items: center;
}
.hidden {
display: none;
}
.modal-content {
background: white;
border-radius: 0.5rem;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.2);
padding: 1.5rem;
width: 24rem;
max-width: 100%;
max-height: 90vh;
display: flex;
flex-direction: column;
}
.language-list {
overflow-y: auto;
flex: 1;
min-height: 0;
margin-bottom: 1rem;
}
.lang-button {
width: 100%;
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem;
border-radius: 0.375rem;
transition: background-color 0.3s;
border: 1px solid #ccc;
background-color: #f8f8f8;
}
.lang-button:hover {
background-color: #ebf8ff;
}
.lang-button.active {
background-color: #bee3f8;
}
.flag-icon {
width: 24px;
height: 16px;
object-fit: contain;
}
.close-button {
background-color: #3182ce;
color: white;
padding: 0.5rem 1rem;
border-radius: 0.375rem;
cursor: pointer;
font-weight: bold;
border: none;
}
.close-button:hover {
background-color: #2b6cb0;
}
`;
private selectLanguage(lang: string) {
this.dispatchEvent(
new CustomEvent("language-selected", {
detail: { lang },
bubbles: true,
composed: true,
}),
);
}
updated(changedProps: Map<string, unknown>) {
if (changedProps.has("visible")) {
if (this.visible) {
document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "auto";
}
}
}
disconnectedCallback() {
super.disconnectedCallback();
document.body.style.overflow = "auto";
}
render() {
return html`
<div class="modal ${this.visible ? "" : "hidden"}">
<div class="modal-content">
<h2 class="text-xl font-semibold mb-4">Select Language</h2>
<div class="language-list">
${this.languageList.map((lang) => {
const isActive = this.currentLang === lang.code;
return html`
<button
class="lang-button ${isActive ? "active" : ""}"
@click=${() => this.selectLanguage(lang.code)}
>
<img
src="/flags/${lang.svg}.svg"
class="flag-icon"
alt="${lang.code}"
/>
<span>${lang.native} (${lang.en})</span>
</button>
`;
})}
</div>
<button
class="close-button"
@click=${() =>
this.dispatchEvent(
new CustomEvent("close-modal", {
bubbles: true,
composed: true,
}),
)}
>
Close
</button>
</div>
</div>
`;
}
}
+7
View File
@@ -17,6 +17,7 @@ import { HostLobbyModal as HostPrivateLobbyModal } from "./HostLobbyModal";
import { JoinPrivateLobbyModal } from "./JoinPrivateLobbyModal"; import { JoinPrivateLobbyModal } from "./JoinPrivateLobbyModal";
import "./LangSelector"; import "./LangSelector";
import { LangSelector } from "./LangSelector"; import { LangSelector } from "./LangSelector";
import { LanguageModal } from "./LanguageModal";
import "./PublicLobby"; import "./PublicLobby";
import { PublicLobby } from "./PublicLobby"; import { PublicLobby } from "./PublicLobby";
import { SinglePlayerModal } from "./SinglePlayerModal"; import { SinglePlayerModal } from "./SinglePlayerModal";
@@ -56,9 +57,15 @@ class Client {
const langSelector = document.querySelector( const langSelector = document.querySelector(
"lang-selector", "lang-selector",
) as LangSelector; ) as LangSelector;
const LanguageModal = document.querySelector(
"lang-selector",
) as LanguageModal;
if (!langSelector) { if (!langSelector) {
consolex.warn("Lang selector element not found"); consolex.warn("Lang selector element not found");
} }
if (!LanguageModal) {
consolex.warn("Language modal element not found");
}
this.flagInput = document.querySelector("flag-input") as FlagInput; this.flagInput = document.querySelector("flag-input") as FlagInput;
if (!this.flagInput) { if (!this.flagInput) {
+12 -12
View File
@@ -35,7 +35,7 @@ export class SinglePlayerModal extends LitElement {
<div class="options-layout"> <div class="options-layout">
<!-- Map Selection --> <!-- Map Selection -->
<div class="options-section"> <div class="options-section">
<div class="option-title">${translateText("single_modal.map")}</div> <div class="option-title">${translateText("map.map")}</div>
<div class="option-cards"> <div class="option-cards">
${Object.entries(GameMapType) ${Object.entries(GameMapType)
.filter(([key]) => isNaN(Number(key))) .filter(([key]) => isNaN(Number(key)))
@@ -80,7 +80,7 @@ export class SinglePlayerModal extends LitElement {
<!-- Difficulty Selection --> <!-- Difficulty Selection -->
<div class="options-section"> <div class="options-section">
<div class="option-title"> <div class="option-title">
${translateText("single_modal.difficulty")} ${translateText("difficulty.difficulty")}
</div> </div>
<div class="option-cards"> <div class="option-cards">
${Object.entries(Difficulty) ${Object.entries(Difficulty)
@@ -160,13 +160,13 @@ export class SinglePlayerModal extends LitElement {
</label> </label>
<label <label
for="disable-npcs" for="singleplayer-modal-disable-npcs"
class="option-card ${this.disableNPCs ? "selected" : ""}" class="option-card ${this.disableNPCs ? "selected" : ""}"
> >
<div class="checkbox-icon"></div> <div class="checkbox-icon"></div>
<input <input
type="checkbox" type="checkbox"
id="disable-npcs" id="singleplayer-modal-disable-npcs"
@change=${this.handleDisableNPCsChange} @change=${this.handleDisableNPCsChange}
.checked=${this.disableNPCs} .checked=${this.disableNPCs}
/> />
@@ -175,13 +175,13 @@ export class SinglePlayerModal extends LitElement {
</div> </div>
</label> </label>
<label <label
for="instant-build" for="singleplayer-modal-instant-build"
class="option-card ${this.instantBuild ? "selected" : ""}" class="option-card ${this.instantBuild ? "selected" : ""}"
> >
<div class="checkbox-icon"></div> <div class="checkbox-icon"></div>
<input <input
type="checkbox" type="checkbox"
id="instant-build" id="singleplayer-modal-instant-build"
@change=${this.handleInstantBuildChange} @change=${this.handleInstantBuildChange}
.checked=${this.instantBuild} .checked=${this.instantBuild}
/> />
@@ -191,13 +191,13 @@ export class SinglePlayerModal extends LitElement {
</label> </label>
<label <label
for="infinite-gold" for="singleplayer-modal-infinite-gold"
class="option-card ${this.infiniteGold ? "selected" : ""}" class="option-card ${this.infiniteGold ? "selected" : ""}"
> >
<div class="checkbox-icon"></div> <div class="checkbox-icon"></div>
<input <input
type="checkbox" type="checkbox"
id="infinite-gold" id="singleplayer-modal-infinite-gold"
@change=${this.handleInfiniteGoldChange} @change=${this.handleInfiniteGoldChange}
.checked=${this.infiniteGold} .checked=${this.infiniteGold}
/> />
@@ -207,13 +207,13 @@ export class SinglePlayerModal extends LitElement {
</label> </label>
<label <label
for="infinite-troops" for="singleplayer-modal-infinite-troops"
class="option-card ${this.infiniteTroops ? "selected" : ""}" class="option-card ${this.infiniteTroops ? "selected" : ""}"
> >
<div class="checkbox-icon"></div> <div class="checkbox-icon"></div>
<input <input
type="checkbox" type="checkbox"
id="infinite-troops" id="singleplayer-modal-infinite-troops"
@change=${this.handleInfiniteTroopsChange} @change=${this.handleInfiniteTroopsChange}
.checked=${this.infiniteTroops} .checked=${this.infiniteTroops}
/> />
@@ -223,13 +223,13 @@ export class SinglePlayerModal extends LitElement {
</label> </label>
<label <label
for="disable-nukes" for="singleplayer-modal-disable-nukes"
class="option-card ${this.disableNukes ? "selected" : ""}" class="option-card ${this.disableNukes ? "selected" : ""}"
> >
<div class="checkbox-icon"></div> <div class="checkbox-icon"></div>
<input <input
type="checkbox" type="checkbox"
id="disable-nukes" id="singleplayer-modal-disable-nukes"
@change=${this.handleDisableNukesChange} @change=${this.handleDisableNukesChange}
.checked=${this.disableNukes} .checked=${this.disableNukes}
/> />
@@ -1,6 +1,7 @@
import { LitElement, html } from "lit"; import { LitElement, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js"; import { classMap } from "lit/directives/class-map.js";
import { translateText } from "../../Utils";
@customElement("o-button") @customElement("o-button")
export class OButton extends LitElement { export class OButton extends LitElement {
@@ -18,7 +19,6 @@ export class OButton extends LitElement {
render() { render() {
return html` return html`
<button <button
data-i18n="${this.translationKey}"
class=${classMap({ class=${classMap({
"c-button": true, "c-button": true,
"c-button--block": this.block, "c-button--block": this.block,
@@ -28,7 +28,9 @@ export class OButton extends LitElement {
})} })}
?disabled=${this.disable} ?disabled=${this.disable}
> >
${this.title} ${`${this.translationKey}` === ""
? `${this.title}`
: `${translateText(this.translationKey)}`}
</button> </button>
`; `;
} }
@@ -1,5 +1,6 @@
import { LitElement, css, html } from "lit"; import { LitElement, css, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
import { translateText } from "../../Utils";
@customElement("o-modal") @customElement("o-modal")
export class OModal extends LitElement { export class OModal extends LitElement {
@@ -74,11 +75,10 @@ export class OModal extends LitElement {
? html` ? html`
<aside class="c-modal"> <aside class="c-modal">
<div class="c-modal__wrapper"> <div class="c-modal__wrapper">
<header <header class="c-modal__header">
class="c-modal__header" ${`${this.translationKey}` === ""
data-i18n="${this.translationKey}" ? `${this.title}`
> : `${translateText(this.translationKey)}`}
${this.title}
<div class="c-modal__close" @click=${this.close}>X</div> <div class="c-modal__close" @click=${this.close}>X</div>
</header> </header>
<section class="c-modal__content"> <section class="c-modal__content">
+3 -2
View File
@@ -1,5 +1,6 @@
import { LitElement, css, html } from "lit"; import { LitElement, css, html } from "lit";
import { customElement, state } from "lit/decorators.js"; import { customElement, state } from "lit/decorators.js";
import { translateText } from "../client/Utils";
@customElement("game-starting-modal") @customElement("game-starting-modal")
export class GameStartingModal extends LitElement { export class GameStartingModal extends LitElement {
@@ -88,8 +89,8 @@ export class GameStartingModal extends LitElement {
render() { render() {
return html` return html`
<div class="modal ${this.isVisible ? "visible" : ""}"> <div class="modal ${this.isVisible ? "visible" : ""}">
<h2>Game is Starting...</h2> <h2>${translateText("game_starting_modal.title")}</h2>
<p>Preparing for the lobby to start. Please wait.</p> <p>${translateText("game_starting_modal.desc")}</p>
</div> </div>
`; `;
} }
+18
View File
@@ -339,6 +339,24 @@
<player-panel></player-panel> <player-panel></player-panel>
<help-modal></help-modal> <help-modal></help-modal>
<dark-mode-button></dark-mode-button> <dark-mode-button></dark-mode-button>
<div
id="language-modal"
class="fixed inset-0 bg-black bg-opacity-50 z-50 hidden flex justify-center items-center"
>
<div class="bg-white rounded-lg shadow-lg p-6 w-96 max-w-full">
<h2 class="text-xl font-semibold mb-4">Select Language</h2>
<div
id="language-list"
class="space-y-2 max-h-80 overflow-y-auto"
></div>
<button
class="mt-4 w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded"
onclick="document.getElementById('language-modal').classList.add('hidden')"
>
Close
</button>
</div>
</div>
<!-- Scripts --> <!-- Scripts -->
<script> <script>
// Remove preload class after everything is loaded // Remove preload class after everything is loaded