Merge branch 'vfoulon80/reorganize-translations' into 'master'

Convert single translation file to a folder

See merge request veloren/veloren!1666
This commit is contained in:
Imbris 2021-01-02 05:51:51 +00:00
commit b61c1e6436
39 changed files with 1108 additions and 715 deletions

View File

@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Doubled range of ScaleMode slider when set to Custom
- Glider can now be deployed even when not on the ground
- Gliding now has an energy cost for strenuous maneuvers based on lift
- Translations are now folders with multiple files instead of a huge single file
### Removed

View File

@ -27,6 +27,7 @@
scale_ratio: 1.0,
),
},
sub_directories: [],
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting

View File

@ -0,0 +1,17 @@
# Translation document instructions
In order to keep localization documents readible please follow the following
rules:
- Separate the string map sections using a commentary describing the purpose
of the next section
- Prepend multi-line strings with a commentary
- Append one blank line after multi-line strings and two blank lines after sections
# Adding a new language in Veloren
To add a new language in Veloren, please follow these steps:
- Create a new folder into the `assets/voxygen/i18n` directory
- Copy the content of the `en` directory in your new folder
- Configure the language metadata in the `_manifest.ron` file
- From this point, you can start translating the files!

View File

@ -39,6 +39,7 @@
scale_ratio: 1.0,
),
},
sub_directories: [],
string_map: {
/// Start Common section
/// Texts used in multiple locations with the same formatting

View File

@ -1,664 +0,0 @@
/// Translation document instructions
///
/// In order to keep localization documents readible please follow the following
/// rules:
/// - separate the string map sections using a commentary describing the purpose
/// of the next section
/// - prepend multi-line strings with a commentary
/// - append one blank lines after a multi-line strings and two after sections
///
/// To add a new language in Veloren, just write an additional `.ron` file in
/// `assets/voxygen/i18n` and that's it!
///
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
metadata: (
language_name: "English",
language_identifier: "en",
),
convert_utf8_to_ascii: false,
fonts: {
"opensans": Font (
asset_key: "voxygen.font.OpenSans-Regular",
scale_ratio: 1.0,
),
"metamorph": Font (
asset_key: "voxygen.font.Metamorphous-Regular",
scale_ratio: 1.0,
),
"alkhemi": Font (
asset_key: "voxygen.font.Alkhemikal",
scale_ratio: 1.0,
),
"wizard": Font (
asset_key: "voxygen.font.wizard",
scale_ratio: 1.0,
),
"cyri": Font (
asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended",
scale_ratio: 1.0,
),
},
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting
"common.username": "username",
"common.singleplayer": "Singleplayer",
"common.multiplayer": "Multiplayer",
"common.servers": "Servers",
"common.quit": "Quit",
"common.settings": "Settings",
"common.languages": "Languages",
"common.interface": "Interface",
"common.gameplay": "Gameplay",
"common.controls": "Controls",
"common.video": "Graphics",
"common.sound": "Sound",
"common.resume": "Resume",
"common.characters": "Characters",
"common.close": "Close",
"common.yes": "Yes",
"common.no": "No",
"common.back": "Back",
"common.create": "Create",
"common.okay": "Okay",
"common.add": "Add",
"common.accept": "Accept",
"common.decline": "Decline",
"common.disclaimer": "Disclaimer",
"common.cancel": "Cancel",
"common.none": "None",
"common.error": "Error",
"common.fatal_error": "Fatal Error",
"common.you": "You",
"common.automatic": "Auto",
"common.random": "Random",
// Settings Window title
"common.interface_settings": "Interface Settings",
"common.gameplay_settings": "Gameplay Settings",
"common.controls_settings": "Controls Settings",
"common.video_settings": "Graphics Settings",
"common.sound_settings": "Sound Settings",
"common.language_settings": "Language Settings",
// Message when connection to the server is lost
"common.connection_lost": r#"Connection lost!
Did the server restart?
Is the client up to date?"#,
"common.species.orc": "Orc",
"common.species.human": "Human",
"common.species.dwarf": "Dwarf",
"common.species.elf": "Elf",
"common.species.undead": "Undead",
"common.species.danari": "Danari",
"common.weapons.axe": "Axe",
"common.weapons.sword": "Sword",
"common.weapons.staff": "Staff",
"common.weapons.bow": "Bow",
"common.weapons.hammer": "Hammer",
"common.weapons.sceptre": "Healing Sceptre",
"common.rand_appearance": "Random appearance and name",
/// End Common section
/// Start Main screen section
"main.username": "Username",
"main.server": "Server",
"main.password": "Password",
"main.connecting": "Connecting",
"main.creating_world": "Creating world",
"main.tip": "Tip:",
// Welcome notice that appears the first time Veloren is started
"main.notice": r#"Welcome to the alpha version of Veloren!
Before you dive into the fun, please keep a few things in mind:
- This is a very early alpha. Expect bugs, extremely unfinished gameplay, unpolished mechanics, and missing features.
- If you have constructive feedback or bug reports, you can contact us via Reddit, GitLab, or our community Discord server.
- Veloren is licensed under the GPL 3 open-source licence. That means you're free to play, modify, and redistribute the game however
you wish (provided derived work is also under GPL 3).
- Veloren is a non-profit community project, and everybody working on it is a volunteer.
If you like what you see, you're welcome to join the development or art teams!
Thanks for taking the time to read this notice, we hope you enjoy the game!
~ The Veloren Devs"#,
// Login process description
"main.login_process": r#"Information on the Login Process:
Please note that you now need an account
to play on auth-enabled servers.
You can create an account over at
https://veloren.net/account/."#,
"main.login.server_not_found": "Server not found",
"main.login.authentication_error": "Auth error on server",
"main.login.server_full": "Server is full",
"main.login.untrusted_auth_server": "Auth server not trusted",
"main.login.outdated_client_or_server": "ServerWentMad: Probably versions are incompatible, check for updates.",
"main.login.timeout": "Timeout: Server did not respond in time. (Overloaded or network issues).",
"main.login.server_shut_down": "Server shut down",
"main.login.already_logged_in": "You are already logged into the server.",
"main.login.network_error": "Network error",
"main.login.failed_sending_request": "Request to Auth server failed",
"main.login.invalid_character": "The selected character is invalid",
"main.login.client_crashed": "Client crashed",
"main.login.not_on_whitelist": "You need a Whitelist entry by an Admin to join",
"main.login.banned": "You have been banned with the following reason",
"main.login.kicked": "You have been kicked with the following reason",
"main.login.select_language": "Select a language",
"main.servers.select_server": "Select a server",
/// End Main screen section
/// Start HUD Section
"hud.do_not_show_on_startup": "Don't show this on Startup",
"hud.show_tips": "Show Tips",
"hud.quests": "Quests",
"hud.you_died": "You Died",
"hud.waypoint_saved": "Waypoint Saved",
"hud.press_key_to_show_keybindings_fmt": "[{key}] Keybindings",
"hud.press_key_to_toggle_lantern_fmt": "[{key}] Lantern",
"hud.press_key_to_show_debug_info_fmt": "Press {key} to show debug info",
"hud.press_key_to_toggle_keybindings_fmt": "Press {key} to toggle keybindings",
"hud.press_key_to_toggle_debug_info_fmt": "Press {key} to toggle debug info",
// Chat outputs
"hud.chat.online_msg": "[{name}] is online now",
"hud.chat.offline_msg": "{name} went offline",
"hud.chat.default_death_msg": "[{name}] died",
"hud.chat.environmental_kill_msg": "[{name}] died in {environment}",
"hud.chat.fall_kill_msg": "[{name}] died from fall damage",
"hud.chat.suicide_msg": "[{name}] died from self-inflicted wounds",
"hud.chat.pvp_melee_kill_msg": "[{attacker}] defeated [{victim}]",
"hud.chat.pvp_ranged_kill_msg": "[{attacker}] shot [{victim}]",
"hud.chat.pvp_explosion_kill_msg": "[{attacker}] blew up [{victim}]",
"hud.chat.pvp_energy_kill_msg": "[{attacker}] killed [{victim}] with magic",
"hud.chat.pvp_buff_kill_msg": "[{attacker}] killed [{victim}]",
"hud.chat.npc_melee_kill_msg": "{attacker} killed [{victim}]",
"hud.chat.npc_ranged_kill_msg": "{attacker} shot [{victim}]",
"hud.chat.npc_explosion_kill_msg": "{attacker} blew up [{victim}]",
"hud.chat.npc_energy_kill_msg": "[{attacker}] killed [{victim}] with magic",
"hud.chat.npc_other_kill_msg": "[{attacker}] killed [{victim}]",
"hud.chat.loot_msg": "You picked up [{item}]",
"hud.chat.loot_fail": "Your Inventory is full!",
"hud.chat.goodbye": "Goodbye!",
"hud.chat.connection_lost": "Connection lost. Kicking in {time} seconds.",
// SCT outputs
"hud.sct.experience": "{amount} Exp",
"hud.sct.block": "BLOCKED",
// Respawn message
"hud.press_key_to_respawn": r#"Press {key} to respawn at the last campfire you visited."#,
// Welcome message
"hud.welcome": r#"Welcome to the Veloren Alpha!
Some tips before you start:
Press F1 to see the available key commands.
Type /help into the chat to see chat commands
There are chests and other objects randomly spawning in the World!
Right-Click to collect them.
To actually use whatever you loot from those chests open your inventory with 'B'.
Double click the items in your bag to use or equip them.
Throw them away by clicking them once and clicking outside of the bag
Nights can get pretty dark in Veloren.
Light your lantern by pressing 'G'
Want to free your cursor to close this window? Press TAB!
Enjoy your stay in the World of Veloren."#,
"hud.temp_quest_headline": r#"Please, help us Traveller!"#,
"hud.temp_quest_text": r#"Dungeons filled with evil cultists
have emerged all around our peaceful towns!
Gather some company, stack up on food
and defeat their vile leaders and acolytes.
Maybe you can even obtain one of their
magically infused items?"#,
// Inventory
"hud.bag.inventory": "{playername}'s Inventory",
"hud.bag.stats_title": "{playername}'s Stats",
"hud.bag.exp": "Exp",
"hud.bag.armor": "Armor",
"hud.bag.stats": "Stats",
"hud.bag.head": "Head",
"hud.bag.neck": "Neck",
"hud.bag.tabard": "Tabard",
"hud.bag.shoulders": "Shoulders",
"hud.bag.chest": "Chest",
"hud.bag.hands": "Hands",
"hud.bag.lantern": "Lantern",
"hud.bag.glider": "Glider",
"hud.bag.belt": "Belt",
"hud.bag.ring": "Ring",
"hud.bag.back": "Back",
"hud.bag.legs": "Legs",
"hud.bag.feet": "Feet",
"hud.bag.mainhand": "Mainhand",
"hud.bag.offhand": "Offhand",
// Map and Questlog
"hud.map.map_title": "Map",
"hud.map.qlog_title": "Quests",
// Settings
"hud.settings.general": "General",
"hud.settings.none": "None",
"hud.settings.press_behavior.toggle": "Toggle",
"hud.settings.press_behavior.hold": "Hold",
"hud.settings.help_window": "Help Window",
"hud.settings.debug_info": "Debug Info",
"hud.settings.tips_on_startup": "Tips-On-Startup",
"hud.settings.ui_scale": "UI-Scale",
"hud.settings.relative_scaling": "Relative Scaling",
"hud.settings.custom_scaling": "Custom Scaling",
"hud.settings.crosshair": "Crosshair",
"hud.settings.transparency": "Transparency",
"hud.settings.hotbar": "Hotbar",
"hud.settings.toggle_shortcuts": "Toggle Shortcuts",
"hud.settings.buffs_skillbar": "Buffs at Skillbar",
"hud.settings.buffs_mmap": "Buffs at Minimap",
"hud.settings.toggle_bar_experience": "Toggle Experience Bar",
"hud.settings.scrolling_combat_text": "Scrolling Combat Text",
"hud.settings.single_damage_number": "Single Damage Numbers",
"hud.settings.cumulated_damage": "Cumulated Damage",
"hud.settings.incoming_damage": "Incoming Damage",
"hud.settings.cumulated_incoming_damage": "Cumulated Incoming Damage",
"hud.settings.speech_bubble": "Speech Bubble",
"hud.settings.speech_bubble_dark_mode": "Speech Bubble Dark Mode",
"hud.settings.speech_bubble_icon": "Speech Bubble Icon",
"hud.settings.energybar_numbers": "Energybar Numbers",
"hud.settings.values": "Values",
"hud.settings.percentages": "Percentages",
"hud.settings.chat": "Chat",
"hud.settings.background_transparency": "Background Transparency",
"hud.settings.chat_character_name": "Character Names in chat",
"hud.settings.loading_tips": "Loading Screen Tips",
"hud.settings.pan_sensitivity": "Pan Sensitivity",
"hud.settings.zoom_sensitivity": "Zoom Sensitivity",
"hud.settings.invert_scroll_zoom": "Invert Scroll Zoom",
"hud.settings.invert_mouse_y_axis": "Invert Mouse Y Axis",
"hud.settings.enable_mouse_smoothing": "Camera Smoothing",
"hud.settings.free_look_behavior": "Free look behavior",
"hud.settings.auto_walk_behavior": "Auto walk behavior",
"hud.settings.stop_auto_walk_on_input": "Stop auto walk on movement",
"hud.settings.view_distance": "View Distance",
"hud.settings.sprites_view_distance": "Sprites View Distance",
"hud.settings.figures_view_distance": "Entities View Distance",
"hud.settings.maximum_fps": "Maximum FPS",
"hud.settings.fov": "Field of View (deg)",
"hud.settings.gamma": "Gamma",
"hud.settings.exposure": "Exposure",
"hud.settings.ambiance": "Ambiance Brightness",
"hud.settings.antialiasing_mode": "AntiAliasing Mode",
"hud.settings.upscale_factor": "Upscale Factor",
"hud.settings.cloud_rendering_mode": "Cloud Rendering Mode",
"hud.settings.fluid_rendering_mode": "Fluid Rendering Mode",
"hud.settings.fluid_rendering_mode.cheap": "Cheap",
"hud.settings.fluid_rendering_mode.shiny": "Shiny",
"hud.settings.cloud_rendering_mode.minimal": "Minimal",
"hud.settings.cloud_rendering_mode.low": "Low",
"hud.settings.cloud_rendering_mode.medium": "Medium",
"hud.settings.cloud_rendering_mode.high": "High",
"hud.settings.cloud_rendering_mode.ultra": "Ultra",
"hud.settings.fullscreen": "Fullscreen",
"hud.settings.fullscreen_mode": "Fullscreen Mode",
"hud.settings.fullscreen_mode.exclusive": "Exclusive",
"hud.settings.fullscreen_mode.borderless": "Borderless",
"hud.settings.particles": "Particles",
"hud.settings.resolution": "Resolution",
"hud.settings.bit_depth": "Bit Depth",
"hud.settings.refresh_rate": "Refresh Rate",
"hud.settings.lighting_rendering_mode": "Lighting Rendering Mode",
"hud.settings.lighting_rendering_mode.ashikhmin": "Type A - High ",
"hud.settings.lighting_rendering_mode.blinnphong": "Type B - Medium",
"hud.settings.lighting_rendering_mode.lambertian": "Type L - Cheap",
"hud.settings.shadow_rendering_mode": "Shadow Rendering Mode",
"hud.settings.shadow_rendering_mode.none": "None",
"hud.settings.shadow_rendering_mode.cheap": "Cheap",
"hud.settings.shadow_rendering_mode.map": "Map",
"hud.settings.shadow_rendering_mode.map.resolution": "Resolution",
"hud.settings.lod_detail": "LoD Detail",
"hud.settings.save_window_size": "Save window size",
"hud.settings.music_volume": "Music Volume",
"hud.settings.sound_effect_volume": "Sound Effects Volume",
"hud.settings.audio_device": "Audio Device",
"hud.settings.awaitingkey": "Press a key...",
"hud.settings.unbound": "None",
"hud.settings.reset_keybinds": "Reset to Defaults",
"hud.social": "Other Players",
"hud.social.online": "Online:",
"hud.social.friends": "Friends",
"hud.social.not_yet_available": "Not yet available",
"hud.social.faction": "Faction",
"hud.social.play_online_fmt": "{nb_player} player(s) online",
"hud.social.name": "Name",
"hud.social.level": "Level",
"hud.social.zone": "Zone",
"hud.social.account": "Account",
"hud.crafting": "Crafting",
"hud.crafting.recipes": "Recipes",
"hud.crafting.ingredients": "Ingredients:",
"hud.crafting.craft": "Craft",
"hud.crafting.tool_cata": "Requires:",
"hud.group": "Group",
"hud.group.invite_to_join": "{name} invited you to their group!",
"hud.group.invite": "Invite",
"hud.group.kick": "Kick",
"hud.group.assign_leader": "Assign Leader",
"hud.group.leave": "Leave Group",
"hud.group.dead" : "Dead",
"hud.group.out_of_range": "Out of range",
"hud.group.add_friend": "Add to Friends",
"hud.group.link_group": "Link Groups",
"hud.group.in_menu": "In Menu",
"hud.group.members": "Group Members",
"hud.spell": "Spells",
"hud.free_look_indicator": "Free look active. Press {key} to disable.",
"hud.auto_walk_indicator": "Auto walk active",
"hud.map.difficulty": "Difficulty",
"hud.map.towns": "Towns",
"hud.map.castles": "Castles",
"hud.map.dungeons": "Dungeons",
"hud.map.caves": "Caves",
"hud.map.cave": "Cave",
"hud.map.town": "Town",
"hud.map.castle": "Castle",
"hud.map.dungeon": "Dungeon",
"hud.map.difficulty_dungeon": "Dungeon\n\nDifficulty: {difficulty}",
"hud.map.drag": "Drag",
"hud.map.zoom": "Zoom",
"hud.map.recenter": "Recenter",
/// End HUD section
/// Start GameInput section
"gameinput.primary": "Basic Attack",
"gameinput.secondary": "Secondary Attack/Block/Aim",
"gameinput.slot1": "Hotbar Slot 1",
"gameinput.slot2": "Hotbar Slot 2",
"gameinput.slot3": "Hotbar Slot 3",
"gameinput.slot4": "Hotbar Slot 4",
"gameinput.slot5": "Hotbar Slot 5",
"gameinput.slot6": "Hotbar Slot 6",
"gameinput.slot7": "Hotbar Slot 7",
"gameinput.slot8": "Hotbar Slot 8",
"gameinput.slot9": "Hotbar Slot 9",
"gameinput.slot10": "Hotbar Slot 10",
"gameinput.swaploadout": "Swap Loadout",
"gameinput.togglecursor": "Toggle Cursor",
"gameinput.help": "Toggle Help Window",
"gameinput.toggleinterface": "Toggle Interface",
"gameinput.toggledebug": "Toggle FPS and Debug Info",
"gameinput.screenshot": "Take Screenshot",
"gameinput.toggleingameui": "Toggle Nametags",
"gameinput.fullscreen": "Toggle Fullscreen",
"gameinput.moveforward": "Move Forward",
"gameinput.moveleft": "Move Left",
"gameinput.moveright": "Move Right",
"gameinput.moveback": "Move Backwards",
"gameinput.jump": "Jump",
"gameinput.glide": "Glider",
"gameinput.roll": "Roll",
"gameinput.climb": "Climb",
"gameinput.climbdown": "Climb Down",
"gameinput.wallleap": "Wall Leap",
"gameinput.togglelantern": "Toggle Lantern",
"gameinput.mount": "Mount",
"gameinput.chat": "Chat",
"gameinput.command": "Command",
"gameinput.escape": "Escape",
"gameinput.map": "Map",
"gameinput.bag": "Bag",
"gameinput.social": "Social",
"gameinput.sit": "Sit",
"gameinput.spellbook": "Spells",
"gameinput.settings": "Settings",
"gameinput.respawn": "Respawn",
"gameinput.charge": "Charge",
"gameinput.togglewield": "Toggle Wield",
"gameinput.interact": "Interact",
"gameinput.freelook": "Free Look",
"gameinput.autowalk": "Auto Walk",
"gameinput.dance": "Dance",
"gameinput.select": "Select Entity",
"gameinput.acceptgroupinvite": "Accept Group Invite",
"gameinput.declinegroupinvite": "Decline Group Invite",
"gameinput.crafting": "Crafting",
"gameinput.fly": "Fly",
"gameinput.sneak": "Sneak",
"gameinput.swimdown": "Swim downwards",
"gameinput.swimup": "Swim upwards",
/// End GameInput section
/// Start chracter selection section
"char_selection.loading_characters": "Loading characters...",
"char_selection.delete_permanently": "Permanently delete this Character?",
"char_selection.deleting_character": "Deleting Character...",
"char_selection.change_server": "Change Server",
"char_selection.enter_world": "Enter World",
"char_selection.logout": "Logout",
"char_selection.create_new_character": "Create New Character",
"char_selection.creating_character": "Creating Character...",
"char_selection.character_creation": "Character Creation",
"char_selection.human_default": "Human Default",
"char_selection.level_fmt": "Level {level_nb}",
"char_selection.uncanny_valley": "Wilderness",
"char_selection.plains_of_uncertainty": "Plains of Uncertainty",
"char_selection.beard": "Beard",
"char_selection.hair_style": "Hair Style",
"char_selection.hair_color": "Hair Color",
"char_selection.eye_color": "Eye Color",
"char_selection.skin": "Skin",
"char_selection.eyeshape": "Eye Details",
"char_selection.accessories": "Accessories",
"char_selection.create_info_name": "Your Character needs a name!",
/// End character selection section
/// Start character window section
"character_window.character_name": "Character Name",
// Character stats
"character_window.character_stats": r#"Endurance
Fitness
Willpower
Protection
"#,
/// End character window section
/// Start Escape Menu Section
"esc_menu.logout": "Logout",
"esc_menu.quit_game": "Quit Game",
/// End Escape Menu Section
/// Buffs and Debuffs
"buff.remove": "Click to remove",
"buff.title.missing": "Missing Title",
"buff.desc.missing": "Missing Description",
// Buffs
"buff.title.heal": "Heal",
"buff.desc.heal": "Gain health over time.",
"buff.title.potion": "Potion",
"buff.desc.potion": "Drinking...",
"buff.title.saturation": "Saturation",
"buff.desc.saturation": "Gain health over time from consumables.",
"buff.title.campfire_heal": "Campfire Heal",
"buff.desc.campfire_heal": "Resting at a campfire heals 1% per second.",
// Debuffs
"debuff.title.bleed": "Bleeding",
"debuff.desc.bleed": "Inflicts regular damage.",
},
vector_map: {
"loading.tips": [
"Press 'G' to light your lantern.",
"Press 'F1' to see all default keybindings.",
"You can type /say or /s to only chat with players directly around you.",
"You can type /region or /r to only chat with players a couple of hundred blocks around you.",
"You can type /group or /g to only chat with players in your current group.",
"To send private messages type /tell followed by a player name and your message.",
"NPCs with the same level can have a different difficulty.",
"Keep an eye out for food, chests and other loot spread all around the world!",
"Inventory filled with food? Try crafting better food from it!",
"Wondering what's there to do? Try out one of the dungeons marked on the map!",
"Don't forget to adjust the graphics for your system. Press 'N' to open the settings.",
"Playing with others is fun! Press 'O' to see who is online.",
"An NPC with a skull beneath their healthbar is quite powerful compared to yourself.",
"Press 'J' to dance. Party!",
"Press 'L-Shift' to open your Glider and conquer the skies.",
"Veloren is still in Pre-Alpha. We do our best to improve it every day!",
"If you want to join the Dev-Team or just have a chat with us join our Discord-Server.",
"You can toggle showing your amount of health on the healthbar in the settings.",
"In order to see your stats click the 'Stats' button in the inventory.",
"Sit near a campfire (with the 'K' key) to rest - receiving a slow heal-over-time.",
],
"npc.speech.villager_under_attack": [
"Help, I'm under attack!",
"Help! I'm under attack!",
"Ouch! I'm under attack!",
"Ouch! I'm under attack! Help!",
"Help me! I'm under attack!",
"I'm under attack! Help!",
"I'm under attack! Help me!",
"Help!",
"Help! Help!",
"Help! Help! Help!",
"I'm under attack!",
"AAAHHH! I'm under attack!",
"AAAHHH! I'm under attack! Help!",
"Help! We're under attack!",
"Help! Murderer!",
"Help! There's a murderer on the loose!",
"Help! They're trying to kill me!",
"Guards, I'm under attack!",
"Guards! I'm under attack!",
"I'm under attack! Guards!",
"Help! Guards! I'm under attack!",
"Guards! Come quick!",
"Guards! Guards!",
"Guards! There's a villain attacking me!",
"Guards, slay this foul villain!",
"Guards! There's a murderer!",
"Guards! Help me!",
"You won't get away with this! Guards!",
"You fiend!",
"Help me!",
"Help! Please!",
"Ouch! Guards! Help!",
"They're coming for me!",
"Help! Help! I'm being repressed!",
"Ah, now we see the violence inherent in the system.",
"Tis but a scratch!",
"Stop that!",
"What did I ever do to you?!",
"Please stop attacking me!",
"Hey! Watch where you point that thing!",
"Heinous wretch, be gone with you!",
"Stop it! Go away!",
"Now you're making me mad!",
"Oi! Who do you think you are?!",
"I'll have your head for that!",
"Stop, please! I carry nothing of value!",
"I'll set my brother on you, he's bigger than I am!",
"Nooo, I'm telling mother!",
"Curse you!",
"Please don't do that.",
"That wasn't very nice!",
"Your weapon works, you can put it away now!",
"Spare me!",
"Please, I have a family!",
"I'm too young to die!",
"Can we talk about this?",
"Violence is never the answer!",
"Today is turning out to be a very bad day...",
"Hey, that hurt!",
"Eek!",
"How rude!",
"Stop, I beg you!",
"A pox upon you!",
"This isn't fun.",
"How dare you?!",
"You'll pay for that!",
"Keep that up and you'll be sorry!",
"Don't make me hurt you!",
"There must be some misunderstanding!",
"You don't need to do this!",
"Be gone, fiend!",
"That really hurt!",
"Why would you do that?",
"By the spirits, cease!",
"You must have me confused with someone else!",
"I don't deserve this!",
"Please don't do that again.",
"Guards, throw this monster in the lake!",
"I'll set my tarrasque on you!",
],
}
)

View File

@ -0,0 +1,145 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
metadata: (
language_name: "English",
language_identifier: "en",
),
convert_utf8_to_ascii: false,
fonts: {
"opensans": Font (
asset_key: "voxygen.font.OpenSans-Regular",
scale_ratio: 1.0,
),
"metamorph": Font (
asset_key: "voxygen.font.Metamorphous-Regular",
scale_ratio: 1.0,
),
"alkhemi": Font (
asset_key: "voxygen.font.Alkhemikal",
scale_ratio: 1.0,
),
"wizard": Font (
asset_key: "voxygen.font.wizard",
scale_ratio: 1.0,
),
"cyri": Font (
asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended",
scale_ratio: 1.0,
),
},
sub_directories: [
"hud"
],
string_map: {
},
vector_map: {
"loading.tips": [
"Press 'G' to light your lantern.",
"Press 'F1' to see all default keybindings.",
"You can type /say or /s to only chat with players directly around you.",
"You can type /region or /r to only chat with players a couple of hundred blocks around you.",
"You can type /group or /g to only chat with players in your current group.",
"To send private messages type /tell followed by a player name and your message.",
"NPCs with the same level can have a different difficulty.",
"Keep an eye out for food, chests and other loot spread all around the world!",
"Inventory filled with food? Try crafting better food from it!",
"Wondering what's there to do? Try out one of the dungeons marked on the map!",
"Don't forget to adjust the graphics for your system. Press 'N' to open the settings.",
"Playing with others is fun! Press 'O' to see who is online.",
"An NPC with a skull beneath their healthbar is quite powerful compared to yourself.",
"Press 'J' to dance. Party!",
"Press 'L-Shift' to open your Glider and conquer the skies.",
"Veloren is still in Pre-Alpha. We do our best to improve it every day!",
"If you want to join the Dev-Team or just have a chat with us join our Discord-Server.",
"You can toggle showing your amount of health on the healthbar in the settings.",
"In order to see your stats click the 'Stats' button in the inventory.",
"Sit near a campfire (with the 'K' key) to rest - receiving a slow heal-over-time.",
],
"npc.speech.villager_under_attack": [
"Help, I'm under attack!",
"Help! I'm under attack!",
"Ouch! I'm under attack!",
"Ouch! I'm under attack! Help!",
"Help me! I'm under attack!",
"I'm under attack! Help!",
"I'm under attack! Help me!",
"Help!",
"Help! Help!",
"Help! Help! Help!",
"I'm under attack!",
"AAAHHH! I'm under attack!",
"AAAHHH! I'm under attack! Help!",
"Help! We're under attack!",
"Help! Murderer!",
"Help! There's a murderer on the loose!",
"Help! They're trying to kill me!",
"Guards, I'm under attack!",
"Guards! I'm under attack!",
"I'm under attack! Guards!",
"Help! Guards! I'm under attack!",
"Guards! Come quick!",
"Guards! Guards!",
"Guards! There's a villain attacking me!",
"Guards, slay this foul villain!",
"Guards! There's a murderer!",
"Guards! Help me!",
"You won't get away with this! Guards!",
"You fiend!",
"Help me!",
"Help! Please!",
"Ouch! Guards! Help!",
"They're coming for me!",
"Help! Help! I'm being repressed!",
"Ah, now we see the violence inherent in the system.",
"Tis but a scratch!",
"Stop that!",
"What did I ever do to you?!",
"Please stop attacking me!",
"Hey! Watch where you point that thing!",
"Heinous wretch, be gone with you!",
"Stop it! Go away!",
"Now you're making me mad!",
"Oi! Who do you think you are?!",
"I'll have your head for that!",
"Stop, please! I carry nothing of value!",
"I'll set my brother on you, he's bigger than I am!",
"Nooo, I'm telling mother!",
"Curse you!",
"Please don't do that.",
"That wasn't very nice!",
"Your weapon works, you can put it away now!",
"Spare me!",
"Please, I have a family!",
"I'm too young to die!",
"Can we talk about this?",
"Violence is never the answer!",
"Today is turning out to be a very bad day...",
"Hey, that hurt!",
"Eek!",
"How rude!",
"Stop, I beg you!",
"A pox upon you!",
"This isn't fun.",
"How dare you?!",
"You'll pay for that!",
"Keep that up and you'll be sorry!",
"Don't make me hurt you!",
"There must be some misunderstanding!",
"You don't need to do this!",
"Be gone, fiend!",
"That really hurt!",
"Why would you do that?",
"By the spirits, cease!",
"You must have me confused with someone else!",
"I don't deserve this!",
"Please don't do that again.",
"Guards, throw this monster in the lake!",
"I'll set my tarrasque on you!",
],
}
)

View File

@ -0,0 +1,22 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
"buff.remove": "Click to remove",
"buff.title.missing": "Missing Title",
"buff.desc.missing": "Missing Description",
"buff.title.heal": "Heal",
"buff.desc.heal": "Gain health over time.",
"buff.title.potion": "Potion",
"buff.desc.potion": "Drinking...",
"buff.title.saturation": "Saturation",
"buff.desc.saturation": "Gain health over time from consumables.",
"buff.title.campfire_heal": "Campfire Heal",
"buff.desc.campfire_heal": "Resting at a campfire heals 1% per second.",
},
vector_map: {
}
)

View File

@ -0,0 +1,31 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
"char_selection.loading_characters": "Loading characters...",
"char_selection.delete_permanently": "Permanently delete this Character?",
"char_selection.deleting_character": "Deleting Character...",
"char_selection.change_server": "Change Server",
"char_selection.enter_world": "Enter World",
"char_selection.logout": "Logout",
"char_selection.create_new_character": "Create New Character",
"char_selection.creating_character": "Creating Character...",
"char_selection.character_creation": "Character Creation",
"char_selection.human_default": "Human Default",
"char_selection.level_fmt": "Level {level_nb}",
"char_selection.uncanny_valley": "Wilderness",
"char_selection.plains_of_uncertainty": "Plains of Uncertainty",
"char_selection.beard": "Beard",
"char_selection.hair_style": "Hair Style",
"char_selection.hair_color": "Hair Color",
"char_selection.eye_color": "Eye Color",
"char_selection.skin": "Skin",
"char_selection.eyeshape": "Eye Details",
"char_selection.accessories": "Accessories",
"char_selection.create_info_name": "Your Character needs a name!",
},
vector_map: {
}
)

View File

@ -0,0 +1,72 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
// Texts used in multiple locations with the same formatting
"common.username": "username",
"common.singleplayer": "Singleplayer",
"common.multiplayer": "Multiplayer",
"common.servers": "Servers",
"common.quit": "Quit",
"common.settings": "Settings",
"common.languages": "Languages",
"common.interface": "Interface",
"common.gameplay": "Gameplay",
"common.controls": "Controls",
"common.video": "Graphics",
"common.sound": "Sound",
"common.resume": "Resume",
"common.characters": "Characters",
"common.close": "Close",
"common.yes": "Yes",
"common.no": "No",
"common.back": "Back",
"common.create": "Create",
"common.okay": "Okay",
"common.add": "Add",
"common.accept": "Accept",
"common.decline": "Decline",
"common.disclaimer": "Disclaimer",
"common.cancel": "Cancel",
"common.none": "None",
"common.error": "Error",
"common.fatal_error": "Fatal Error",
"common.you": "You",
"common.automatic": "Auto",
"common.random": "Random",
// Settings Window title
"common.interface_settings": "Interface Settings",
"common.gameplay_settings": "Gameplay Settings",
"common.controls_settings": "Controls Settings",
"common.video_settings": "Graphics Settings",
"common.sound_settings": "Sound Settings",
"common.language_settings": "Language Settings",
// Message when connection to the server is lost
"common.connection_lost": r#"Connection lost!
Did the server restart?
Is the client up to date?"#,
"common.species.orc": "Orc",
"common.species.human": "Human",
"common.species.dwarf": "Dwarf",
"common.species.elf": "Elf",
"common.species.undead": "Undead",
"common.species.danari": "Danari",
"common.weapons.axe": "Axe",
"common.weapons.sword": "Sword",
"common.weapons.staff": "Staff",
"common.weapons.bow": "Bow",
"common.weapons.hammer": "Hammer",
"common.weapons.sceptre": "Healing Sceptre",
"common.rand_appearance": "Random appearance and name",
},
vector_map: {
}
)

View File

@ -0,0 +1,13 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
"debuff.title.bleed": "Bleeding",
"debuff.desc.bleed": "Inflicts regular damage.",
},
vector_map: {
}
)

View File

@ -0,0 +1,13 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
"esc_menu.logout": "Logout",
"esc_menu.quit_game": "Quit Game",
},
vector_map: {
}
)

View File

@ -0,0 +1,67 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
"gameinput.primary": "Basic Attack",
"gameinput.secondary": "Secondary Attack/Block/Aim",
"gameinput.slot1": "Hotbar Slot 1",
"gameinput.slot2": "Hotbar Slot 2",
"gameinput.slot3": "Hotbar Slot 3",
"gameinput.slot4": "Hotbar Slot 4",
"gameinput.slot5": "Hotbar Slot 5",
"gameinput.slot6": "Hotbar Slot 6",
"gameinput.slot7": "Hotbar Slot 7",
"gameinput.slot8": "Hotbar Slot 8",
"gameinput.slot9": "Hotbar Slot 9",
"gameinput.slot10": "Hotbar Slot 10",
"gameinput.swaploadout": "Swap Loadout",
"gameinput.togglecursor": "Toggle Cursor",
"gameinput.help": "Toggle Help Window",
"gameinput.toggleinterface": "Toggle Interface",
"gameinput.toggledebug": "Toggle FPS and Debug Info",
"gameinput.screenshot": "Take Screenshot",
"gameinput.toggleingameui": "Toggle Nametags",
"gameinput.fullscreen": "Toggle Fullscreen",
"gameinput.moveforward": "Move Forward",
"gameinput.moveleft": "Move Left",
"gameinput.moveright": "Move Right",
"gameinput.moveback": "Move Backwards",
"gameinput.jump": "Jump",
"gameinput.glide": "Glider",
"gameinput.roll": "Roll",
"gameinput.climb": "Climb",
"gameinput.climbdown": "Climb Down",
"gameinput.wallleap": "Wall Leap",
"gameinput.togglelantern": "Toggle Lantern",
"gameinput.mount": "Mount",
"gameinput.chat": "Chat",
"gameinput.command": "Command",
"gameinput.escape": "Escape",
"gameinput.map": "Map",
"gameinput.bag": "Bag",
"gameinput.social": "Social",
"gameinput.sit": "Sit",
"gameinput.spellbook": "Spells",
"gameinput.settings": "Settings",
"gameinput.respawn": "Respawn",
"gameinput.charge": "Charge",
"gameinput.togglewield": "Toggle Wield",
"gameinput.interact": "Interact",
"gameinput.freelook": "Free Look",
"gameinput.autowalk": "Auto Walk",
"gameinput.dance": "Dance",
"gameinput.select": "Select Entity",
"gameinput.acceptgroupinvite": "Accept Group Invite",
"gameinput.declinegroupinvite": "Decline Group Invite",
"gameinput.crafting": "Crafting",
"gameinput.fly": "Fly",
"gameinput.sneak": "Sneak",
"gameinput.swimdown": "Swim downwards",
"gameinput.swimup": "Swim upwards",
},
vector_map: {
}
)

View File

@ -0,0 +1,32 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
// Inventory
"hud.bag.inventory": "{playername}'s Inventory",
"hud.bag.stats_title": "{playername}'s Stats",
"hud.bag.exp": "Exp",
"hud.bag.armor": "Armor",
"hud.bag.stats": "Stats",
"hud.bag.head": "Head",
"hud.bag.neck": "Neck",
"hud.bag.tabard": "Tabard",
"hud.bag.shoulders": "Shoulders",
"hud.bag.chest": "Chest",
"hud.bag.hands": "Hands",
"hud.bag.lantern": "Lantern",
"hud.bag.glider": "Glider",
"hud.bag.belt": "Belt",
"hud.bag.ring": "Ring",
"hud.bag.back": "Back",
"hud.bag.legs": "Legs",
"hud.bag.feet": "Feet",
"hud.bag.mainhand": "Mainhand",
"hud.bag.offhand": "Offhand",
},
vector_map: {
}
)

View File

@ -0,0 +1,21 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
"character_window.character_name": "Character Name",
// Character stats
"character_window.character_stats": r#"Endurance
Fitness
Willpower
Protection
"#,
},
vector_map: {
}
)

View File

@ -0,0 +1,37 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
// Chat outputs
"hud.chat.online_msg": "[{name}] is online now",
"hud.chat.offline_msg": "{name} went offline",
"hud.chat.default_death_msg": "[{name}] died",
"hud.chat.environmental_kill_msg": "[{name}] died in {environment}",
"hud.chat.fall_kill_msg": "[{name}] died from fall damage",
"hud.chat.suicide_msg": "[{name}] died from self-inflicted wounds",
"hud.chat.pvp_melee_kill_msg": "[{attacker}] defeated [{victim}]",
"hud.chat.pvp_ranged_kill_msg": "[{attacker}] shot [{victim}]",
"hud.chat.pvp_explosion_kill_msg": "[{attacker}] blew up [{victim}]",
"hud.chat.pvp_energy_kill_msg": "[{attacker}] killed [{victim}] with magic",
"hud.chat.pvp_buff_kill_msg": "[{attacker}] killed [{victim}]",
"hud.chat.npc_melee_kill_msg": "{attacker} killed [{victim}]",
"hud.chat.npc_ranged_kill_msg": "{attacker} shot [{victim}]",
"hud.chat.npc_explosion_kill_msg": "{attacker} blew up [{victim}]",
"hud.chat.npc_energy_kill_msg": "[{attacker}] killed [{victim}] with magic",
"hud.chat.npc_other_kill_msg": "[{attacker}] killed [{victim}]",
"hud.chat.loot_msg": "You picked up [{item}]",
"hud.chat.loot_fail": "Your Inventory is full!",
"hud.chat.goodbye": "Goodbye!",
"hud.chat.connection_lost": "Connection lost. Kicking in {time} seconds.",
},
vector_map: {
}
)

View File

@ -0,0 +1,16 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
"hud.crafting": "Crafting",
"hud.crafting.recipes": "Recipes",
"hud.crafting.ingredients": "Ingredients:",
"hud.crafting.craft": "Craft",
"hud.crafting.tool_cata": "Requires:",
},
vector_map: {
}
)

View File

@ -0,0 +1,23 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
"hud.group": "Group",
"hud.group.invite_to_join": "{name} invited you to their group!",
"hud.group.invite": "Invite",
"hud.group.kick": "Kick",
"hud.group.assign_leader": "Assign Leader",
"hud.group.leave": "Leave Group",
"hud.group.dead" : "Dead",
"hud.group.out_of_range": "Out of range",
"hud.group.add_friend": "Add to Friends",
"hud.group.link_group": "Link Groups",
"hud.group.in_menu": "In Menu",
"hud.group.members": "Group Members",
},
vector_map: {
}
)

View File

@ -0,0 +1,101 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
// Settings
"hud.settings.general": "General",
"hud.settings.none": "None",
"hud.settings.press_behavior.toggle": "Toggle",
"hud.settings.press_behavior.hold": "Hold",
"hud.settings.help_window": "Help Window",
"hud.settings.debug_info": "Debug Info",
"hud.settings.tips_on_startup": "Tips-On-Startup",
"hud.settings.ui_scale": "UI-Scale",
"hud.settings.relative_scaling": "Relative Scaling",
"hud.settings.custom_scaling": "Custom Scaling",
"hud.settings.crosshair": "Crosshair",
"hud.settings.transparency": "Transparency",
"hud.settings.hotbar": "Hotbar",
"hud.settings.toggle_shortcuts": "Toggle Shortcuts",
"hud.settings.buffs_skillbar": "Buffs at Skillbar",
"hud.settings.buffs_mmap": "Buffs at Minimap",
"hud.settings.toggle_bar_experience": "Toggle Experience Bar",
"hud.settings.scrolling_combat_text": "Scrolling Combat Text",
"hud.settings.single_damage_number": "Single Damage Numbers",
"hud.settings.cumulated_damage": "Cumulated Damage",
"hud.settings.incoming_damage": "Incoming Damage",
"hud.settings.cumulated_incoming_damage": "Cumulated Incoming Damage",
"hud.settings.speech_bubble": "Speech Bubble",
"hud.settings.speech_bubble_dark_mode": "Speech Bubble Dark Mode",
"hud.settings.speech_bubble_icon": "Speech Bubble Icon",
"hud.settings.energybar_numbers": "Energybar Numbers",
"hud.settings.values": "Values",
"hud.settings.percentages": "Percentages",
"hud.settings.chat": "Chat",
"hud.settings.background_transparency": "Background Transparency",
"hud.settings.chat_character_name": "Character Names in chat",
"hud.settings.loading_tips": "Loading Screen Tips",
"hud.settings.pan_sensitivity": "Pan Sensitivity",
"hud.settings.zoom_sensitivity": "Zoom Sensitivity",
"hud.settings.invert_scroll_zoom": "Invert Scroll Zoom",
"hud.settings.invert_mouse_y_axis": "Invert Mouse Y Axis",
"hud.settings.enable_mouse_smoothing": "Camera Smoothing",
"hud.settings.free_look_behavior": "Free look behavior",
"hud.settings.auto_walk_behavior": "Auto walk behavior",
"hud.settings.stop_auto_walk_on_input": "Stop auto walk on movement",
"hud.settings.view_distance": "View Distance",
"hud.settings.sprites_view_distance": "Sprites View Distance",
"hud.settings.figures_view_distance": "Entities View Distance",
"hud.settings.maximum_fps": "Maximum FPS",
"hud.settings.fov": "Field of View (deg)",
"hud.settings.gamma": "Gamma",
"hud.settings.exposure": "Exposure",
"hud.settings.ambiance": "Ambiance Brightness",
"hud.settings.antialiasing_mode": "AntiAliasing Mode",
"hud.settings.upscale_factor": "Upscale Factor",
"hud.settings.cloud_rendering_mode": "Cloud Rendering Mode",
"hud.settings.fluid_rendering_mode": "Fluid Rendering Mode",
"hud.settings.fluid_rendering_mode.cheap": "Cheap",
"hud.settings.fluid_rendering_mode.shiny": "Shiny",
"hud.settings.cloud_rendering_mode.minimal": "Minimal",
"hud.settings.cloud_rendering_mode.low": "Low",
"hud.settings.cloud_rendering_mode.medium": "Medium",
"hud.settings.cloud_rendering_mode.high": "High",
"hud.settings.cloud_rendering_mode.ultra": "Ultra",
"hud.settings.fullscreen": "Fullscreen",
"hud.settings.fullscreen_mode": "Fullscreen Mode",
"hud.settings.fullscreen_mode.exclusive": "Exclusive",
"hud.settings.fullscreen_mode.borderless": "Borderless",
"hud.settings.particles": "Particles",
"hud.settings.resolution": "Resolution",
"hud.settings.bit_depth": "Bit Depth",
"hud.settings.refresh_rate": "Refresh Rate",
"hud.settings.lighting_rendering_mode": "Lighting Rendering Mode",
"hud.settings.lighting_rendering_mode.ashikhmin": "Type A - High ",
"hud.settings.lighting_rendering_mode.blinnphong": "Type B - Medium",
"hud.settings.lighting_rendering_mode.lambertian": "Type L - Cheap",
"hud.settings.shadow_rendering_mode": "Shadow Rendering Mode",
"hud.settings.shadow_rendering_mode.none": "None",
"hud.settings.shadow_rendering_mode.cheap": "Cheap",
"hud.settings.shadow_rendering_mode.map": "Map",
"hud.settings.shadow_rendering_mode.map.resolution": "Resolution",
"hud.settings.lod_detail": "LoD Detail",
"hud.settings.save_window_size": "Save window size",
"hud.settings.music_volume": "Music Volume",
"hud.settings.sound_effect_volume": "Sound Effects Volume",
"hud.settings.audio_device": "Audio Device",
"hud.settings.awaitingkey": "Press a key...",
"hud.settings.unbound": "None",
"hud.settings.reset_keybinds": "Reset to Defaults",
},
vector_map: {
}
)

View File

@ -0,0 +1,27 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
// Map and Questlog
"hud.map.map_title": "Map",
"hud.map.qlog_title": "Quests",
"hud.map.difficulty": "Difficulty",
"hud.map.towns": "Towns",
"hud.map.castles": "Castles",
"hud.map.dungeons": "Dungeons",
"hud.map.caves": "Caves",
"hud.map.cave": "Cave",
"hud.map.town": "Town",
"hud.map.castle": "Castle",
"hud.map.dungeon": "Dungeon",
"hud.map.difficulty_dungeon": "Dungeon\n\nDifficulty: {difficulty}",
"hud.map.drag": "Drag",
"hud.map.zoom": "Zoom",
"hud.map.recenter": "Recenter",
},
vector_map: {
}
)

View File

@ -0,0 +1,75 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
"hud.do_not_show_on_startup": "Don't show this on Startup",
"hud.show_tips": "Show Tips",
"hud.quests": "Quests",
"hud.you_died": "You Died",
"hud.waypoint_saved": "Waypoint Saved",
"hud.press_key_to_show_keybindings_fmt": "[{key}] Keybindings",
"hud.press_key_to_toggle_lantern_fmt": "[{key}] Lantern",
"hud.press_key_to_show_debug_info_fmt": "Press {key} to show debug info",
"hud.press_key_to_toggle_keybindings_fmt": "Press {key} to toggle keybindings",
"hud.press_key_to_toggle_debug_info_fmt": "Press {key} to toggle debug info",
// Respawn message
"hud.press_key_to_respawn": r#"Press {key} to respawn at the last campfire you visited."#,
// Welcome message
"hud.welcome": r#"Welcome to the Veloren Alpha!
Some tips before you start:
Press F1 to see the available key commands.
Type /help into the chat to see chat commands
There are chests and other objects randomly spawning in the World!
Right-Click to collect them.
To actually use whatever you loot from those chests open your inventory with 'B'.
Double click the items in your bag to use or equip them.
Throw them away by clicking them once and clicking outside of the bag
Nights can get pretty dark in Veloren.
Light your lantern by pressing 'G'
Want to free your cursor to close this window? Press TAB!
Enjoy your stay in the World of Veloren."#,
"hud.temp_quest_headline": r#"Please, help us Traveller!"#,
"hud.temp_quest_text": r#"Dungeons filled with evil cultists
have emerged all around our peaceful towns!
Gather some company, stack up on food
and defeat their vile leaders and acolytes.
Maybe you can even obtain one of their
magically infused items?"#,
"hud.spell": "Spells",
"hud.free_look_indicator": "Free look active. Press {key} to disable.",
"hud.auto_walk_indicator": "Auto walk active",
},
vector_map: {
}
)

View File

@ -0,0 +1,14 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
// SCT outputs
"hud.sct.experience": "{amount} Exp",
"hud.sct.block": "BLOCKED",
},
vector_map: {
}
)

View File

@ -0,0 +1,22 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
"hud.social": "Other Players",
"hud.social.online": "Online:",
"hud.social.friends": "Friends",
"hud.social.not_yet_available": "Not yet available",
"hud.social.faction": "Faction",
"hud.social.play_online_fmt": "{nb_player} player(s) online",
"hud.social.name": "Name",
"hud.social.level": "Level",
"hud.social.zone": "Zone",
"hud.social.account": "Account",
},
vector_map: {
}
)

View File

@ -0,0 +1,66 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
/// Start Main screen section
"main.username": "Username",
"main.server": "Server",
"main.password": "Password",
"main.connecting": "Connecting",
"main.creating_world": "Creating world",
"main.tip": "Tip:",
// Welcome notice that appears the first time Veloren is started
"main.notice": r#"Welcome to the alpha version of Veloren!
Before you dive into the fun, please keep a few things in mind:
- This is a very early alpha. Expect bugs, extremely unfinished gameplay, unpolished mechanics, and missing features.
- If you have constructive feedback or bug reports, you can contact us via Reddit, GitLab, or our community Discord server.
- Veloren is licensed under the GPL 3 open-source licence. That means you're free to play, modify, and redistribute the game however
you wish (provided derived work is also under GPL 3).
- Veloren is a non-profit community project, and everybody working on it is a volunteer.
If you like what you see, you're welcome to join the development or art teams!
Thanks for taking the time to read this notice, we hope you enjoy the game!
~ The Veloren Devs"#,
// Login process description
"main.login_process": r#"Information on the Login Process:
Please note that you now need an account
to play on auth-enabled servers.
You can create an account over at
https://veloren.net/account/."#,
"main.login.server_not_found": "Server not found",
"main.login.authentication_error": "Auth error on server",
"main.login.server_full": "Server is full",
"main.login.untrusted_auth_server": "Auth server not trusted",
"main.login.outdated_client_or_server": "ServerWentMad: Probably versions are incompatible, check for updates.",
"main.login.timeout": "Timeout: Server did not respond in time. (Overloaded or network issues).",
"main.login.server_shut_down": "Server shut down",
"main.login.already_logged_in": "You are already logged into the server.",
"main.login.network_error": "Network error",
"main.login.failed_sending_request": "Request to Auth server failed",
"main.login.invalid_character": "The selected character is invalid",
"main.login.client_crashed": "Client crashed",
"main.login.not_on_whitelist": "You need a Whitelist entry by an Admin to join",
"main.login.banned": "You have been banned with the following reason",
"main.login.kicked": "You have been kicked with the following reason",
"main.login.select_language": "Select a language",
"main.servers.select_server": "Select a server",
/// End Main screen section
},
vector_map: {
}
)

View File

@ -0,0 +1,12 @@
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" English
(
string_map: {
},
vector_map: {
}
)

View File

@ -40,6 +40,7 @@
scale_ratio: 1.0,
),
},
sub_directories: [],
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting

View File

@ -41,6 +41,7 @@
scale_ratio: 1.0,
),
},
sub_directories: [],
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting

View File

@ -27,6 +27,7 @@
scale_ratio: 0.9,
),
},
sub_directories: [],
string_map: {
// Common texts used in multiple locations
"common.username": "pseudo",

View File

@ -42,6 +42,8 @@
scale_ratio: 1.0,
),
},
sub_directories: [],
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting

View File

@ -41,6 +41,7 @@
scale_ratio: 1.0,
),
},
sub_directories: [],
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting

View File

@ -41,6 +41,7 @@
scale_ratio: 1.0,
),
},
sub_directories: [],
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting

View File

@ -27,6 +27,7 @@
scale_ratio: 1.0,
),
},
sub_directories: [],
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting

View File

@ -27,6 +27,7 @@
scale_ratio: 1.0,
),
},
sub_directories: [],
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting

View File

@ -41,6 +41,7 @@
scale_ratio: 1.0,
),
},
sub_directories: [],
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting

View File

@ -40,6 +40,7 @@
scale_ratio: 1.0,
),
},
sub_directories: [],
string_map: {
/// Start Common section

View File

@ -41,6 +41,7 @@
scale_ratio: 1.0,
),
},
sub_directories: [],
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting

View File

@ -41,6 +41,7 @@
scale_ratio: 1.0,
),
},
sub_directories: [],
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting

View File

@ -41,6 +41,7 @@
scale_ratio: 0.75,
),
},
sub_directories: [],
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting

View File

@ -27,6 +27,7 @@
scale_ratio: 0.75,
),
},
sub_directories: [],
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting

View File

@ -2,13 +2,14 @@ use common::assets::{self, AssetExt};
use deunicode::deunicode;
use hashbrown::{HashMap, HashSet};
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use tracing::warn;
/// The reference language, aka the more up-to-date localization data.
/// Also the default language at first startup.
pub const REFERENCE_LANG: &str = "en";
pub const LANG_MANIFEST_FILE: &str = "_manifest";
/// How a language can be described
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct LanguageMetadata {
@ -42,9 +43,25 @@ impl Font {
/// Store font metadata
pub type Fonts = HashMap<String, Font>;
/// Raw localization data, expect the strings to not be loaded here
/// However, metadata informations are correct
/// See `Localization` for more info on each attributes
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct RawLocalization {
pub sub_directories: Vec<String>,
pub string_map: HashMap<String, String>,
pub vector_map: HashMap<String, Vec<String>>,
pub convert_utf8_to_ascii: bool,
pub fonts: Fonts,
pub metadata: LanguageMetadata,
}
/// Store internationalization data
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Localization {
/// A list of subdirectories to lookup for localization files
pub sub_directories: Vec<String>,
/// A map storing the localized texts
///
/// Localized content can be accessed using a String key.
@ -65,6 +82,21 @@ pub struct Localization {
pub metadata: LanguageMetadata,
}
/// Store internationalization maps
/// These structs are meant to be merged into a Localization
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct LocalizationFragment {
/// A map storing the localized texts
///
/// Localized content can be accessed using a String key.
pub string_map: HashMap<String, String>,
/// A map for storing variations of localized texts, for example multiple
/// ways of saying "Help, I'm under attack". Used primarily for npc
/// dialogue.
pub vector_map: HashMap<String, Vec<String>>,
}
impl Localization {
/// Get a localized text from the given key
///
@ -131,42 +163,107 @@ impl Localization {
}
}
}
impl From<RawLocalization> for Localization {
fn from(raw: RawLocalization) -> Self {
Self {
sub_directories: raw.sub_directories,
string_map: raw.string_map,
vector_map: raw.vector_map,
convert_utf8_to_ascii: raw.convert_utf8_to_ascii,
fonts: raw.fonts,
metadata: raw.metadata,
}
}
}
impl From<RawLocalization> for LocalizationFragment {
fn from(raw: RawLocalization) -> Self {
Self {
string_map: raw.string_map,
vector_map: raw.vector_map,
}
}
}
impl assets::Asset for Localization {
type Loader = LocalizationLoader;
impl assets::Asset for RawLocalization {
type Loader = assets::RonLoader;
const EXTENSION: &'static str = "ron";
}
impl assets::Asset for LocalizationFragment {
type Loader = assets::RonLoader;
const EXTENSION: &'static str = "ron";
}
pub struct LocalizationLoader;
impl assets::Loader<Localization> for LocalizationLoader {
fn load(content: Cow<[u8]>, ext: &str) -> Result<Localization, assets::BoxedError> {
let mut asked_localization: Localization = assets::RonLoader::load(content, ext)?;
impl assets::Compound for Localization {
fn load<S: assets::source::Source>(
cache: &assets::AssetCache<S>,
asset_key: &str,
) -> Result<Self, assets::Error> {
let raw = cache
.load::<RawLocalization>(&(asset_key.to_string() + "." + LANG_MANIFEST_FILE))?
.cloned();
let mut localization = Localization::from(raw);
// Walk through files in the folder, collecting localization fragment to merge
// inside the asked_localization
for localization_asset in cache.load_dir::<LocalizationFragment>(asset_key)?.iter() {
localization
.string_map
.extend(localization_asset.read().string_map.clone());
localization
.vector_map
.extend(localization_asset.read().vector_map.clone());
}
// Use the localization's subdirectory list to load fragments from there
for sub_directory in localization.sub_directories.iter() {
for localization_asset in cache
.load_dir::<LocalizationFragment>(&(asset_key.to_string() + "." + &sub_directory))?
.iter()
{
localization
.string_map
.extend(localization_asset.read().string_map.clone());
localization
.vector_map
.extend(localization_asset.read().vector_map.clone());
}
}
// Update the text if UTF-8 to ASCII conversion is enabled
if asked_localization.convert_utf8_to_ascii {
for value in asked_localization.string_map.values_mut() {
if localization.convert_utf8_to_ascii {
for value in localization.string_map.values_mut() {
*value = deunicode(value);
}
for value in asked_localization.vector_map.values_mut() {
for value in localization.vector_map.values_mut() {
*value = value.iter().map(|s| deunicode(s)).collect();
}
}
asked_localization.metadata.language_name =
deunicode(&asked_localization.metadata.language_name);
localization.metadata.language_name = deunicode(&localization.metadata.language_name);
Ok(asked_localization)
Ok(localization)
}
}
/// Load all the available languages located in the voxygen asset directory
pub fn list_localizations() -> Vec<LanguageMetadata> {
assets::load_dir::<Localization>("voxygen.i18n")
.unwrap()
.iter_all()
.filter_map(|(_, lang)| lang.ok().map(|e| e.read().metadata.clone()))
.collect()
let mut languages = vec![];
// List language directories
for i18n_directory in std::fs::read_dir("assets/voxygen/i18n").unwrap() {
if let Ok(i18n_entry) = i18n_directory {
if let Some(i18n_key) = i18n_entry.file_name().to_str() {
// load the root file of all the subdirectories
if let Ok(localization) = RawLocalization::load(
&("voxygen.i18n.".to_string() + i18n_key + "." + LANG_MANIFEST_FILE),
) {
languages.push(localization.read().metadata.clone());
}
}
}
}
languages
}
/// Return the asset associated with the language_id
@ -174,7 +271,7 @@ pub fn i18n_asset_key(language_id: &str) -> String { "voxygen.i18n.".to_string()
#[cfg(test)]
mod tests {
use super::Localization;
use super::{LocalizationFragment, RawLocalization, LANG_MANIFEST_FILE, REFERENCE_LANG};
use git2::Repository;
use hashbrown::{HashMap, HashSet};
use ron::de::{from_bytes, from_reader};
@ -183,15 +280,12 @@ mod tests {
path::{Path, PathBuf},
};
/// List localization files as a PathBuf vector
fn i18n_files(i18n_dir: &Path) -> Vec<PathBuf> {
/// List localization directories as a PathBuf vector
fn i18n_directories(i18n_dir: &Path) -> Vec<PathBuf> {
fs::read_dir(i18n_dir)
.unwrap()
.map(|res| res.map(|e| e.path()).unwrap())
.filter(|e| match e.extension() {
Some(ext) => ext == "ron",
None => false,
})
.filter(|e| e.is_dir())
.collect()
}
@ -247,7 +341,7 @@ mod tests {
fn generate_key_version<'a>(
repo: &'a git2::Repository,
localization: &Localization,
localization: &LocalizationFragment,
path: &std::path::Path,
file_blob: &git2::Blob,
) -> HashMap<String, LocalizationEntryState> {
@ -321,42 +415,129 @@ mod tests {
keys
}
fn complete_key_versions<'a>(
repo: &'a git2::Repository,
head_ref: &git2::Reference,
i18n_key_versions: &mut HashMap<String, LocalizationEntryState>,
dir: &Path,
) {
let root_dir = std::env::current_dir()
.map(|p| p.parent().expect("").to_owned())
.unwrap();
for i18n_file in root_dir.join(&dir).read_dir().unwrap() {
if let Ok(i18n_file) = i18n_file {
if let Ok(file_type) = i18n_file.file_type() {
if file_type.is_file() {
let full_path = i18n_file.path();
let path = full_path.strip_prefix(&root_dir).unwrap();
println!("-> {:?}", i18n_file.file_name());
let i18n_blob = read_file_from_path(&repo, &head_ref, &path);
let i18n: LocalizationFragment = match from_bytes(i18n_blob.content()) {
Ok(v) => v,
Err(e) => {
eprintln!(
"Could not parse {} RON file, skipping: {}",
i18n_file.path().to_string_lossy(),
e
);
continue;
},
};
i18n_key_versions
.extend(generate_key_version(&repo, &i18n, &path, &i18n_blob));
}
}
}
}
}
fn verify_localization_directory(directory_path: &Path) {
let root_dir = std::env::current_dir()
.map(|p| p.parent().expect("").to_owned())
.unwrap();
// Walk through each file in the directory
for i18n_file in root_dir.join(&directory_path).read_dir().unwrap() {
if let Ok(i18n_file) = i18n_file {
if let Ok(file_type) = i18n_file.file_type() {
// Skip folders and the manifest file (which does not contain the same struct we
// want to load)
if file_type.is_file()
&& i18n_file.file_name().to_string_lossy()
!= (LANG_MANIFEST_FILE.to_string() + ".ron")
{
let full_path = i18n_file.path();
println!("-> {:?}", full_path.strip_prefix(&root_dir).unwrap());
let f = fs::File::open(&full_path).expect("Failed opening file");
let _: LocalizationFragment = match from_reader(f) {
Ok(v) => v,
Err(e) => {
panic!(
"Could not parse {} RON file, error: {}",
full_path.to_string_lossy(),
e
);
},
};
}
}
}
}
}
// Test to verify all languages that they are VALID and loadable, without
// need of git just on the local assets folder
#[test]
fn verify_all_localizations() {
// Generate paths
let i18n_asset_path = Path::new("assets/voxygen/i18n/");
let en_i18n_path = i18n_asset_path.join("en.ron");
let ref_i18n_dir_path = i18n_asset_path.join(REFERENCE_LANG);
let ref_i18n_path = ref_i18n_dir_path.join(LANG_MANIFEST_FILE.to_string() + ".ron");
let root_dir = std::env::current_dir()
.map(|p| p.parent().expect("").to_owned())
.unwrap();
assert!(
root_dir.join(&en_i18n_path).is_file(),
"en reference files doesn't exist, something is wrong!"
root_dir.join(&ref_i18n_dir_path).is_dir(),
"Reference language folder doesn't exist, something is wrong!"
);
let i18n_files = i18n_files(&root_dir.join(i18n_asset_path));
assert!(
root_dir.join(&ref_i18n_path).is_file(),
"Reference language manifest file doesn't exist, something is wrong!"
);
let i18n_directories = i18n_directories(&root_dir.join(i18n_asset_path));
// This simple check ONLY guarantees that an arbitrary minimum of translation
// files exists. It's just to notice unintentional deletion of all
// files, or modifying the paths. In case you want to delete all
// language you have to adjust this number:
assert!(
i18n_files.len() > 5,
"have less than 5 translation files, arbitrary minimum check failed. Maybe the i18n \
i18n_directories.len() > 5,
"have less than 5 translation folders, arbitrary minimum check failed. Maybe the i18n \
folder is empty?"
);
for path in i18n_files {
let f = fs::File::open(&path).expect("Failed opening file");
let _: Localization = match from_reader(f) {
for i18n_directory in i18n_directories {
// Attempt to load the manifest file
let manifest_path = i18n_directory.join(LANG_MANIFEST_FILE.to_string() + ".ron");
println!(
"verifying {:?}",
manifest_path.strip_prefix(&root_dir).unwrap()
);
let f = fs::File::open(&manifest_path).expect("Failed opening file");
let raw_localization: RawLocalization = match from_reader(f) {
Ok(v) => v,
Err(e) => {
panic!(
"Could not parse {} RON file, error: {}",
path.to_string_lossy(),
i18n_directory.to_string_lossy(),
e
);
},
};
// Walk through each files and try to load them
verify_localization_directory(&i18n_directory);
// Walk through each subdirectories and try to load files in them
for sub_directory in raw_localization.sub_directories.iter() {
let subdir_path = &i18n_directory.join(sub_directory);
verify_localization_directory(&subdir_path);
}
}
}
@ -367,14 +548,21 @@ mod tests {
fn test_all_localizations() {
// Generate paths
let i18n_asset_path = Path::new("assets/voxygen/i18n/");
let en_i18n_path = i18n_asset_path.join("en.ron");
let ref_i18n_dir_path = i18n_asset_path.join(REFERENCE_LANG);
let ref_i18n_path = ref_i18n_dir_path.join(LANG_MANIFEST_FILE.to_string() + ".ron");
let root_dir = std::env::current_dir()
.map(|p| p.parent().expect("").to_owned())
.unwrap();
let i18n_path = root_dir.join(i18n_asset_path);
if !root_dir.join(&en_i18n_path).is_file() {
panic!("Reference language file not found {:?}", &en_i18n_path)
if !root_dir.join(&ref_i18n_dir_path).is_dir() {
panic!(
"Reference language folder not found {:?}",
&ref_i18n_dir_path
)
}
if !root_dir.join(&ref_i18n_path).is_file() {
panic!("Reference language file not found {:?}", &ref_i18n_path)
}
// Initialize Git objects
@ -385,18 +573,31 @@ mod tests {
let head_ref = repo.head().expect("Impossible to get the HEAD reference");
// Read HEAD for the reference language file
let i18n_en_blob = read_file_from_path(&repo, &head_ref, &en_i18n_path);
let loc: Localization = from_bytes(i18n_en_blob.content())
let i18n_ref_blob = read_file_from_path(&repo, &head_ref, &ref_i18n_path);
let loc: RawLocalization = from_bytes(i18n_ref_blob.content())
.expect("Expect to parse reference i18n RON file, can't proceed without it");
let i18n_references: HashMap<String, LocalizationEntryState> =
generate_key_version(&repo, &loc, &en_i18n_path, &i18n_en_blob);
let mut i18n_references: HashMap<String, LocalizationEntryState> = generate_key_version(
&repo,
&LocalizationFragment::from(loc.clone()),
&ref_i18n_path,
&i18n_ref_blob,
);
// read HEAD for the fragment files
complete_key_versions(&repo, &head_ref, &mut i18n_references, &ref_i18n_dir_path);
// read HEAD for the subfolders
for sub_directory in loc.sub_directories.iter() {
let subdir_path = &ref_i18n_dir_path.join(sub_directory);
complete_key_versions(&repo, &head_ref, &mut i18n_references, &subdir_path);
}
// Compare to other reference files
let i18n_files = i18n_files(&i18n_path);
let i18n_directories = i18n_directories(&i18n_path);
let mut i18n_entry_counts: HashMap<PathBuf, (usize, usize, usize, usize)> = HashMap::new();
for file in &i18n_files {
let relfile = file.strip_prefix(&root_dir).unwrap();
if relfile == en_i18n_path {
for file in &i18n_directories {
let reldir = file.strip_prefix(&root_dir).unwrap();
let relfile = reldir.join(&(LANG_MANIFEST_FILE.to_string() + ".ron"));
if relfile == ref_i18n_path {
continue;
}
println!("\n-----------------------------------");
@ -405,7 +606,7 @@ mod tests {
// Find the localization entry state
let current_blob = read_file_from_path(&repo, &head_ref, &relfile);
let current_loc: Localization = match from_bytes(current_blob.content()) {
let current_loc: RawLocalization = match from_bytes(current_blob.content()) {
Ok(v) => v,
Err(e) => {
eprintln!(
@ -416,8 +617,20 @@ mod tests {
continue;
},
};
let mut current_i18n =
generate_key_version(&repo, &current_loc, &relfile, &current_blob);
let mut current_i18n = generate_key_version(
&repo,
&LocalizationFragment::from(current_loc.clone()),
&relfile,
&current_blob,
);
// read HEAD for the fragment files
complete_key_versions(&repo, &head_ref, &mut current_i18n, &reldir);
// read HEAD for the subfolders
for sub_directory in current_loc.sub_directories.iter() {
let subdir_path = &reldir.join(sub_directory);
complete_key_versions(&repo, &head_ref, &mut current_i18n, &subdir_path);
}
for (ref_key, ref_state) in i18n_references.iter() {
match current_i18n.get_mut(ref_key) {
Some(state) => {
@ -478,7 +691,7 @@ mod tests {
"State",
"Key name",
relfile.to_str().unwrap(),
en_i18n_path.to_str().unwrap()
ref_i18n_path.to_str().unwrap()
);
let mut sorted_keys: Vec<&String> = current_i18n.keys().collect();