mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2024-11-22 05:33:02 +00:00
make localization system dynamic
This commit is contained in:
parent
3d86995feb
commit
028c60157d
|
@ -1,4 +1,8 @@
|
|||
{
|
||||
"name": "English",
|
||||
"font": "csfont.fnt",
|
||||
"font_scale": "0.5",
|
||||
|
||||
"common": {
|
||||
"name": "doukutsu-rs",
|
||||
"back": "< Back",
|
|
@ -1,4 +1,8 @@
|
|||
{
|
||||
"name": "Japanese",
|
||||
"font": "csfontjp.fnt",
|
||||
"font_scale": "0.5",
|
||||
|
||||
"common": {
|
||||
"name": "doukutsu-rs",
|
||||
"back": "< 戻る",
|
|
@ -181,6 +181,13 @@ impl BuiltinFS {
|
|||
),
|
||||
],
|
||||
),
|
||||
FSNode::Directory(
|
||||
"locale",
|
||||
vec![
|
||||
FSNode::File("en.json", include_bytes!("builtin/builtin_data/locale/en.json")),
|
||||
FSNode::File("jp.json", include_bytes!("builtin/builtin_data/locale/jp.json")),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
FSNode::Directory(
|
||||
|
@ -196,13 +203,6 @@ impl BuiltinFS {
|
|||
"lightmap",
|
||||
vec![FSNode::File("spot.png", include_bytes!("builtin/lightmap/spot.png"))],
|
||||
),
|
||||
FSNode::Directory(
|
||||
"locale",
|
||||
vec![
|
||||
FSNode::File("en.json", include_bytes!("builtin/locale/en.json")),
|
||||
FSNode::File("jp.json", include_bytes!("builtin/locale/jp.json")),
|
||||
],
|
||||
),
|
||||
],
|
||||
)],
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::graphics;
|
|||
use crate::input::touch_controls::TouchControlType;
|
||||
use crate::player::Player;
|
||||
use crate::scripting::tsc::text_script::TextScriptExecutionState;
|
||||
use crate::shared_game_state::{Language, SharedGameState};
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::stage::Stage;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
|
@ -197,7 +197,7 @@ impl MapSystem {
|
|||
graphics::draw_rect(ctx, rect_black_bar, Color::new(0.0, 0.0, 0.0, 1.0))?;
|
||||
}
|
||||
|
||||
let map_name = if state.settings.locale == Language::Japanese {
|
||||
let map_name = if state.constants.is_cs_plus && state.settings.locale == "jp" {
|
||||
stage.data.name_jp.chars()
|
||||
} else {
|
||||
stage.data.name.chars()
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::i18n::Locale;
|
|||
use crate::player::ControlMode;
|
||||
use crate::scripting::tsc::text_script::TextScriptEncoding;
|
||||
use crate::settings::Settings;
|
||||
use crate::shared_game_state::{FontData, Language, Season};
|
||||
use crate::shared_game_state::{FontData, Season};
|
||||
use crate::sound::pixtone::{Channel, Envelope, PixToneParameters, Waveform};
|
||||
use crate::sound::SoundManager;
|
||||
|
||||
|
@ -341,7 +341,7 @@ pub struct EngineConstants {
|
|||
pub animated_face_table: Vec<AnimatedFace>,
|
||||
pub string_table: HashMap<String, String>,
|
||||
pub missile_flags: Vec<u16>,
|
||||
pub locales: HashMap<String, Locale>,
|
||||
pub locales: Vec<Locale>,
|
||||
pub gamepad: GamepadConsts,
|
||||
}
|
||||
|
||||
|
@ -1671,7 +1671,7 @@ impl EngineConstants {
|
|||
animated_face_table: vec![AnimatedFace { face_id: 0, anim_id: 0, anim_frames: vec![(0, 0)] }],
|
||||
string_table: HashMap::new(),
|
||||
missile_flags: vec![200, 201, 202, 218, 550, 766, 880, 920, 1551],
|
||||
locales: HashMap::new(),
|
||||
locales: Vec::new(),
|
||||
gamepad: GamepadConsts {
|
||||
button_rects: HashMap::from([
|
||||
(Button::North, GamepadConsts::rects(Rect::new(0, 0, 32, 16))),
|
||||
|
@ -1787,8 +1787,8 @@ impl EngineConstants {
|
|||
|
||||
pub fn rebuild_path_list(&mut self, mod_path: Option<String>, season: Season, settings: &Settings) {
|
||||
self.base_paths.clear();
|
||||
self.base_paths.push("/".to_owned());
|
||||
self.base_paths.push("/builtin/builtin_data/".to_owned());
|
||||
self.base_paths.push("/".to_owned());
|
||||
|
||||
if self.is_cs_plus {
|
||||
self.base_paths.insert(0, "/base/".to_owned());
|
||||
|
@ -1803,12 +1803,12 @@ impl EngineConstants {
|
|||
}
|
||||
}
|
||||
|
||||
if settings.locale != Language::English {
|
||||
self.base_paths.insert(0, format!("/base/{}/", settings.locale.to_language_code()));
|
||||
if settings.locale != "en".to_string() {
|
||||
self.base_paths.insert(0, format!("/base/{}/", settings.locale));
|
||||
}
|
||||
} else {
|
||||
if settings.locale != Language::English {
|
||||
self.base_paths.insert(0, format!("/{}/", settings.locale.to_language_code()));
|
||||
if settings.locale != "en".to_string() {
|
||||
self.base_paths.insert(0, format!("/{}/", settings.locale));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1876,15 +1876,27 @@ impl EngineConstants {
|
|||
pub fn load_locales(&mut self, ctx: &mut Context) -> GameResult {
|
||||
self.locales.clear();
|
||||
|
||||
for language in Language::values() {
|
||||
// Only Switch 1.3+ data contains an entirely valid JP font
|
||||
let font = if language == Language::Japanese && filesystem::exists(ctx, "/base/credit_jp.tsc") {
|
||||
FontData::new("csfontjp.fnt".to_owned(), 0.5, 0.0)
|
||||
} else {
|
||||
language.font()
|
||||
let locale_files = filesystem::read_dir_find(ctx, &self.base_paths, "locale/");
|
||||
|
||||
for locale_file in locale_files.unwrap() {
|
||||
if locale_file.extension().unwrap() != "json" {
|
||||
continue;
|
||||
}
|
||||
|
||||
let locale_code = {
|
||||
let filename = locale_file.file_name().unwrap().to_string_lossy();
|
||||
let mut parts = filename.split('.');
|
||||
parts.next().unwrap().to_string()
|
||||
};
|
||||
self.locales.insert(language.to_string(), Locale::new(ctx, language.to_language_code(), font));
|
||||
log::info!("Loaded locale {} ({}).", language.to_string(), language.to_language_code());
|
||||
|
||||
let mut locale = Locale::new(ctx, &self.base_paths, &locale_code);
|
||||
|
||||
if locale_code == "jp" && filesystem::exists(ctx, "/base/credit_jp.tsc") {
|
||||
locale.set_font(FontData::new("csfontjp.fnt".to_owned(), 0.5, 0.0));
|
||||
}
|
||||
|
||||
self.locales.push(locale.clone());
|
||||
log::info!("Loaded locale {} ({})", locale_code, locale.name.clone());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -325,7 +325,6 @@ pub fn exists_find<P: AsRef<path::Path>>(ctx: &Context, roots: &Vec<String>, pat
|
|||
false
|
||||
}
|
||||
|
||||
|
||||
/// Check whether a path points at a file.
|
||||
pub fn is_file<P: AsRef<path::Path>>(ctx: &Context, path: P) -> bool {
|
||||
ctx.filesystem.is_file(path)
|
||||
|
@ -344,6 +343,26 @@ pub fn read_dir<P: AsRef<path::Path>>(ctx: &Context, path: P) -> GameResult<Box<
|
|||
ctx.filesystem.read_dir(path)
|
||||
}
|
||||
|
||||
pub fn read_dir_find<P: AsRef<path::Path>>(
|
||||
ctx: &Context,
|
||||
roots: &Vec<String>,
|
||||
path: P,
|
||||
) -> GameResult<Box<dyn Iterator<Item = path::PathBuf>>> {
|
||||
let mut files = Vec::new();
|
||||
|
||||
for root in roots {
|
||||
let mut full_path = root.to_string();
|
||||
full_path.push_str(path.as_ref().to_string_lossy().as_ref());
|
||||
|
||||
let result = ctx.filesystem.read_dir(full_path);
|
||||
if result.is_ok() {
|
||||
files.push(result.unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Box::new(files.into_iter().flatten()))
|
||||
}
|
||||
|
||||
/// Adds the given (absolute) path to the list of directories
|
||||
/// it will search to look for resources.
|
||||
///
|
||||
|
|
26
src/i18n.rs
26
src/i18n.rs
|
@ -5,24 +5,26 @@ use std::collections::HashMap;
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Locale {
|
||||
strings: HashMap<String, String>,
|
||||
pub code: String,
|
||||
pub name: String,
|
||||
pub font: FontData,
|
||||
strings: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl Locale {
|
||||
pub fn new(ctx: &mut Context, code: &str, font: FontData) -> Locale {
|
||||
let mut filename = "en.json".to_owned();
|
||||
|
||||
if code != "en" && filesystem::exists(ctx, &format!("/builtin/locale/{}.json", code)) {
|
||||
filename = format!("{}.json", code);
|
||||
}
|
||||
|
||||
let file = filesystem::open(ctx, &format!("/builtin/locale/{}", filename)).unwrap();
|
||||
pub fn new(ctx: &mut Context, base_paths: &Vec<String>, code: &str) -> Locale {
|
||||
let file = filesystem::open_find(ctx, base_paths, &format!("locale/{}.json", code)).unwrap();
|
||||
let json: serde_json::Value = serde_json::from_reader(file).unwrap();
|
||||
|
||||
let strings = Locale::flatten(&json);
|
||||
|
||||
Locale { strings, font }
|
||||
let name = strings["name"].clone();
|
||||
|
||||
let font_name = strings["font"].clone();
|
||||
let font_scale = strings["font_scale"].parse::<f32>().unwrap_or(1.0);
|
||||
let font = FontData::new(font_name, font_scale, 0.0);
|
||||
|
||||
Locale { code: code.to_string(), name, font, strings }
|
||||
}
|
||||
|
||||
fn flatten(json: &serde_json::Value) -> HashMap<String, String> {
|
||||
|
@ -60,4 +62,8 @@ impl Locale {
|
|||
|
||||
string
|
||||
}
|
||||
|
||||
pub fn set_font(&mut self, font: FontData) {
|
||||
self.font = font;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ pub struct Menu<T: std::cmp::PartialEq> {
|
|||
pub non_interactive: bool,
|
||||
}
|
||||
|
||||
impl<T: std::cmp::PartialEq + std::default::Default + Copy> Menu<T> {
|
||||
impl<T: std::cmp::PartialEq + std::default::Default + Clone> Menu<T> {
|
||||
pub fn new(x: isize, y: isize, width: u16, height: u16) -> Menu<T> {
|
||||
Menu {
|
||||
x,
|
||||
|
@ -716,7 +716,7 @@ impl<T: std::cmp::PartialEq + std::default::Default + Copy> Menu<T> {
|
|||
|
||||
if let Some((id, entry)) = self.entries.get(selected) {
|
||||
if entry.selectable() {
|
||||
self.selected = *id;
|
||||
self.selected = id.clone();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -727,7 +727,7 @@ impl<T: std::cmp::PartialEq + std::default::Default + Copy> Menu<T> {
|
|||
|
||||
let mut y = self.y as f32 + 8.0;
|
||||
for (id, entry) in self.entries.iter_mut() {
|
||||
let idx = *id;
|
||||
let idx = id.clone();
|
||||
let entry_bounds = Rect::new_size(self.x, y as isize, self.width as isize, entry.height() as isize);
|
||||
let right_entry_bounds =
|
||||
Rect::new_size(self.x + self.width as isize, y as isize, self.width as isize, entry.height() as isize);
|
||||
|
@ -747,7 +747,7 @@ impl<T: std::cmp::PartialEq + std::default::Default + Copy> Menu<T> {
|
|||
|| state.touch_controls.consume_click_in(entry_bounds) =>
|
||||
{
|
||||
state.sound_manager.play_sfx(18);
|
||||
self.selected = idx;
|
||||
self.selected = idx.clone();
|
||||
return MenuSelectionResult::Selected(idx, entry);
|
||||
}
|
||||
MenuEntry::Options(_, _, _) | MenuEntry::OptionsBar(_, _)
|
||||
|
@ -755,35 +755,35 @@ impl<T: std::cmp::PartialEq + std::default::Default + Copy> Menu<T> {
|
|||
|| state.touch_controls.consume_click_in(left_entry_bounds) =>
|
||||
{
|
||||
state.sound_manager.play_sfx(1);
|
||||
return MenuSelectionResult::Left(self.selected, entry, -1);
|
||||
return MenuSelectionResult::Left(self.selected.clone(), entry, -1);
|
||||
}
|
||||
MenuEntry::Options(_, _, _) | MenuEntry::OptionsBar(_, _)
|
||||
if (self.selected == idx && controller.trigger_right())
|
||||
|| state.touch_controls.consume_click_in(right_entry_bounds) =>
|
||||
{
|
||||
state.sound_manager.play_sfx(1);
|
||||
return MenuSelectionResult::Right(self.selected, entry, 1);
|
||||
return MenuSelectionResult::Right(self.selected.clone(), entry, 1);
|
||||
}
|
||||
MenuEntry::DescriptiveOptions(_, _, _, _)
|
||||
if (self.selected == idx && controller.trigger_left())
|
||||
|| state.touch_controls.consume_click_in(left_entry_bounds) =>
|
||||
{
|
||||
state.sound_manager.play_sfx(1);
|
||||
return MenuSelectionResult::Left(self.selected, entry, -1);
|
||||
return MenuSelectionResult::Left(self.selected.clone(), entry, -1);
|
||||
}
|
||||
MenuEntry::DescriptiveOptions(_, _, _, _) | MenuEntry::SaveData(_)
|
||||
if (self.selected == idx && controller.trigger_right())
|
||||
|| state.touch_controls.consume_click_in(right_entry_bounds) =>
|
||||
{
|
||||
state.sound_manager.play_sfx(1);
|
||||
return MenuSelectionResult::Right(self.selected, entry, 1);
|
||||
return MenuSelectionResult::Right(self.selected.clone(), entry, 1);
|
||||
}
|
||||
MenuEntry::Control(_, _) => {
|
||||
if self.selected == idx && controller.trigger_ok()
|
||||
|| state.touch_controls.consume_click_in(entry_bounds)
|
||||
{
|
||||
state.sound_manager.play_sfx(18);
|
||||
self.selected = idx;
|
||||
self.selected = idx.clone();
|
||||
return MenuSelectionResult::Selected(idx, entry);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,7 @@ use crate::input::combined_menu_controller::CombinedMenuController;
|
|||
use crate::menu::MenuEntry;
|
||||
use crate::menu::{Menu, MenuSelectionResult};
|
||||
use crate::scene::title_scene::TitleScene;
|
||||
use crate::shared_game_state::{
|
||||
CutsceneSkipMode, Language, ScreenShakeIntensity, SharedGameState, TimingMode, WindowMode,
|
||||
};
|
||||
use crate::shared_game_state::{CutsceneSkipMode, ScreenShakeIntensity, SharedGameState, TimingMode, WindowMode};
|
||||
use crate::sound::InterpolationMode;
|
||||
use crate::{graphics, VSyncMode};
|
||||
|
||||
|
@ -95,16 +93,16 @@ impl Default for SoundtrackMenuEntry {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
enum LanguageMenuEntry {
|
||||
Title,
|
||||
Language(Language),
|
||||
Language(String),
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Default for LanguageMenuEntry {
|
||||
fn default() -> Self {
|
||||
LanguageMenuEntry::Language(Language::English)
|
||||
LanguageMenuEntry::Back
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,8 +278,9 @@ impl SettingsMenu {
|
|||
|
||||
self.language.push_entry(LanguageMenuEntry::Title, MenuEntry::Disabled(state.t("menus.options_menu.language")));
|
||||
|
||||
for language in Language::values() {
|
||||
self.language.push_entry(LanguageMenuEntry::Language(language), MenuEntry::Active(language.to_string()));
|
||||
for locale in &state.constants.locales {
|
||||
self.language
|
||||
.push_entry(LanguageMenuEntry::Language(locale.code.clone()), MenuEntry::Active(locale.name.clone()));
|
||||
}
|
||||
|
||||
self.language.push_entry(LanguageMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||
|
@ -460,7 +459,6 @@ impl SettingsMenu {
|
|||
self.current = CurrentMenu::ControlsMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Language, _) => {
|
||||
self.language.selected = LanguageMenuEntry::Language(state.settings.locale);
|
||||
self.current = CurrentMenu::LanguageMenu;
|
||||
}
|
||||
MenuSelectionResult::Selected(MainMenuEntry::Behavior, _) => {
|
||||
|
|
|
@ -48,7 +48,7 @@ use crate::scene::Scene;
|
|||
use crate::scripting::tsc::credit_script::CreditScriptVM;
|
||||
use crate::scripting::tsc::text_script::{ScriptMode, TextScriptExecutionState, TextScriptVM};
|
||||
use crate::settings::ControllerType;
|
||||
use crate::shared_game_state::{CutsceneSkipMode, Language, PlayerCount, ReplayState, SharedGameState, TileSize};
|
||||
use crate::shared_game_state::{CutsceneSkipMode, PlayerCount, ReplayState, SharedGameState, TileSize};
|
||||
use crate::stage::{BackgroundType, Stage, StageTexturePaths};
|
||||
use crate::texture_set::SpriteBatch;
|
||||
use crate::weapon::bullet::BulletManager;
|
||||
|
@ -2182,7 +2182,7 @@ impl Scene for GameScene {
|
|||
let map_name = if self.stage.data.name == "u" {
|
||||
state.constants.title.intro_text.chars()
|
||||
} else {
|
||||
if state.settings.locale == Language::Japanese {
|
||||
if state.constants.is_cs_plus && state.settings.locale == "jp" {
|
||||
self.stage.data.name_jp.chars()
|
||||
} else {
|
||||
self.stage.data.name.chars()
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::input::keyboard_player_controller::KeyboardController;
|
|||
use crate::input::player_controller::PlayerController;
|
||||
use crate::input::touch_player_controller::TouchPlayerController;
|
||||
use crate::player::TargetPlayer;
|
||||
use crate::shared_game_state::{CutsceneSkipMode, Language, ScreenShakeIntensity, TimingMode, WindowMode};
|
||||
use crate::shared_game_state::{CutsceneSkipMode, ScreenShakeIntensity, TimingMode, WindowMode};
|
||||
use crate::sound::InterpolationMode;
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
|
@ -68,7 +68,7 @@ pub struct Settings {
|
|||
#[serde(skip)]
|
||||
pub debug_outlines: bool,
|
||||
pub fps_counter: bool,
|
||||
pub locale: Language,
|
||||
pub locale: String,
|
||||
#[serde(default = "default_window_mode")]
|
||||
pub window_mode: WindowMode,
|
||||
#[serde(default = "default_vsync")]
|
||||
|
@ -89,7 +89,7 @@ fn default_true() -> bool {
|
|||
|
||||
#[inline(always)]
|
||||
fn current_version() -> u32 {
|
||||
19
|
||||
21
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -118,8 +118,8 @@ fn default_vol() -> f32 {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn default_locale() -> Language {
|
||||
Language::English
|
||||
fn default_locale() -> String {
|
||||
"en".to_string()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -303,6 +303,17 @@ impl Settings {
|
|||
self.cutscene_skip_mode = CutsceneSkipMode::Hold;
|
||||
}
|
||||
|
||||
if self.version == 20 {
|
||||
self.version = 21;
|
||||
|
||||
self.locale = match self.locale.as_str() {
|
||||
"English" => "en".to_string(),
|
||||
"Japanese" => "jp".to_string(),
|
||||
|
||||
_ => default_locale(),
|
||||
};
|
||||
}
|
||||
|
||||
if self.version != initial_version {
|
||||
log::info!("Upgraded configuration file from version {} to {}.", initial_version, self.version);
|
||||
}
|
||||
|
@ -400,7 +411,7 @@ impl Default for Settings {
|
|||
infinite_booster: false,
|
||||
debug_outlines: false,
|
||||
fps_counter: false,
|
||||
locale: Language::English,
|
||||
locale: default_locale(),
|
||||
window_mode: WindowMode::Windowed,
|
||||
vsync_mode: VSyncMode::VSync,
|
||||
screen_shake_intensity: ScreenShakeIntensity::Full,
|
||||
|
|
|
@ -118,44 +118,6 @@ impl GameDifficulty {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash, num_derive::FromPrimitive, serde::Serialize, serde::Deserialize)]
|
||||
pub enum Language {
|
||||
English,
|
||||
Japanese,
|
||||
}
|
||||
|
||||
impl Language {
|
||||
pub fn to_language_code(self) -> &'static str {
|
||||
match self {
|
||||
Language::English => "en",
|
||||
Language::Japanese => "jp",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string(self) -> String {
|
||||
match self {
|
||||
Language::English => "English".to_string(),
|
||||
Language::Japanese => "Japanese".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn font(self) -> FontData {
|
||||
match self {
|
||||
Language::English => FontData::new("csfont.fnt".to_owned(), 0.5, 0.0),
|
||||
// Use default as fallback if no proper JP font is found
|
||||
Language::Japanese => FontData::new("0.fnt".to_owned(), 1.0, 0.0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_primitive(val: usize) -> Language {
|
||||
return num_traits::FromPrimitive::from_usize(val).unwrap_or(Language::English);
|
||||
}
|
||||
|
||||
pub fn values() -> Vec<Language> {
|
||||
vec![Language::English, Language::Japanese]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, num_derive::FromPrimitive, serde::Serialize, serde::Deserialize)]
|
||||
pub enum ScreenShakeIntensity {
|
||||
Full,
|
||||
|
@ -399,12 +361,12 @@ impl SharedGameState {
|
|||
}
|
||||
}
|
||||
|
||||
constants.load_locales(ctx)?;
|
||||
|
||||
let season = Season::current();
|
||||
constants.rebuild_path_list(None, season, &settings);
|
||||
|
||||
let active_locale = constants.locales.get(&settings.locale.to_string()).unwrap();
|
||||
constants.load_locales(ctx)?;
|
||||
|
||||
let active_locale = SharedGameState::active_locale(settings.locale.clone(), constants.clone());
|
||||
|
||||
if constants.is_cs_plus {
|
||||
constants.font_scale = active_locale.font.scale;
|
||||
|
@ -843,9 +805,30 @@ impl SharedGameState {
|
|||
return self.difficulty as u16;
|
||||
}
|
||||
|
||||
pub fn get_active_locale(&self) -> &Locale {
|
||||
let active_locale = self.constants.locales.get(&self.settings.locale.to_string()).unwrap();
|
||||
return active_locale;
|
||||
fn active_locale(user_locale: String, constants: EngineConstants) -> Locale {
|
||||
let mut active_locale: Option<Locale> = None;
|
||||
let mut en_locale: Option<Locale> = None;
|
||||
|
||||
for locale in &constants.locales {
|
||||
if locale.code == "en" {
|
||||
en_locale = Some(locale.clone());
|
||||
}
|
||||
|
||||
if locale.code == user_locale {
|
||||
active_locale = Some(locale.clone());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
match active_locale {
|
||||
Some(locale) => locale,
|
||||
None => en_locale.unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_active_locale(&self) -> Locale {
|
||||
let locale = SharedGameState::active_locale(self.settings.locale.clone(), self.constants.clone());
|
||||
locale.clone()
|
||||
}
|
||||
|
||||
pub fn t(&self, key: &str) -> String {
|
||||
|
|
Loading…
Reference in a new issue