Skip to content

Implement language settings from Thirsty CoilSnake - #324

Open
gabblstack wants to merge 1 commit into
pk-hack:masterfrom
gabblstack:master
Open

Implement language settings from Thirsty CoilSnake#324
gabblstack wants to merge 1 commit into
pk-hack:masterfrom
gabblstack:master

Conversation

@gabblstack

Copy link
Copy Markdown

Not everything has been fully translated yet like certain console strings.

  • English
  • Japanese (日本語)

Code by cooprocks123e & Gabbi

Not everything has been fully translated yet like certain console strings.
- English
- Japanese (日本語)

Code by cooprocks123e & Gabbi
@mrtenda

mrtenda commented Jul 20, 2025

Copy link
Copy Markdown
Collaborator

Is it too much trouble for the language file to be a csv instead of a json? csv would be much easier for translators

@PhoenixBound PhoenixBound left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like I never submitted this review last year(!). Sorry about that. By now, neither of us probably fully remembers how this code works... That being said, most of the language-relevant changes are just to use a lot less + with strings and a lot more .format(...).

I already mentioned on Discord how translations require maintenance as text in a program is added and changed. If we do end up merging a localization system, it would be nice to have a translator for any added languages to ping before a release and get things fixed up, to avoid sending the user an exe where many options are in one language and there's a few dialogue boxes in another. (But first we probably need to get an actual regular release schedule, maybe... Jank Jam 4 is getting dangerously close.)

Comment thread coilsnake/ui/gui.py
Comment on lines +137 to +139
self.guistrings.get("ask_enable_debug_prompt")
+ self.guistrings.get("coilsnake_is_running")
+ self.guistrings.get("advanced_users"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In all of these places where multiple strings are fetched from the file and concatenated together, there should just be one string. The only reason they were concatenated together in the first place was to avoid making long lines that require a lot of sideways scrolling to read. (Note that some cases relied on Python concatenating adjacent string literals automatically.)

(Other instances: lines 153-155; 169-171; 208-209; 301-302; 339-344; 380-382; 413-415)

Comment thread coilsnake/ui/gui.py
Comment on lines +195 to +198
self.guistrings.get("java_following_loc")
+ system_java_exe + "\n\n"
+ "To use this installation of Java, select \"Yes\".\n\n"
+ "To override and instead use a different version of Java, select \"No\".",
+ self.guistrings.get("select_yes")
+ self.guistrings.get("select_yes"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You replaced these two unique lines with the same line repeated twice. Combine into one string and use string formatting:

self.guistrings.get("java_detected_at_following_location").format(system_java_exe)

Comment thread coilsnake/ui/gui.py
def create_gui(self):
self.root = Tk()
self.root.wm_title("CoilSnake " + information.VERSION)
self.guistrings.change_language(language_name="en") #replace this with [whatever is in Preferences when we put default language in the preferences stuff]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: maybe adjust this comment to begin with TODO: so that it's easier to search for/easier to see in certain text editors

Comment thread coilsnake/ui/gui.py
Comment on lines +647 to +662
last_used_temporary_menu_index = 1
def add_menu_item_and_get_index(self, menu: Menu, command=None, submenu=None) -> int:
templabel = f"MyTemp{self.last_used_temporary_menu_index}"
self.last_used_temporary_menu_index += 1
if command:
menu.add_command(label=templabel, command=command)
elif submenu:
menu.add_cascade(label=templabel, menu=submenu)
item_index = menu.index(templabel)
return item_index

def _add_translated_menu_item(self, menu: Menu, label_string_name: str, command=None, submenu=None):
index = self.add_menu_item_and_get_index(menu, command=command, submenu=submenu)
def translation_callback():
menu.entryconfigure(index, label=self.guistrings.get(label_string_name))
self.guistrings.register_callback(translation_callback)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this adding a unique temporary label to a menu item...?

Are there problems if you don't put any label on a menu item? If so, does it need to be 100% unique? Would label_string_name itself be unique enough of a label?

Comment on lines -265 to +269
# TODO do some check so that unallocated ranges don't overlap
cur_begin, cur_end = range
for prev_begin, prev_end in self.unallocated_ranges:
if prev_begin <= cur_end and cur_begin <= prev_end:
raise InvalidArgumentError(f"Couldn't mark range ({cur_begin:#x}, {cur_end:#x}) as free "
f"because it overlaps with ({prev_begin:#x}, {prev_end:#x})")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an unrelated change that I already made a PR for (#318). Probably shouldn't be included in this PR. Same goes for the Mother 2 ROM type stuff since Mother 2 support isn't added in this PR

Comment thread coilsnake/lang/ja.json
@@ -0,0 +1,156 @@
{
"coilsnake_name": "まきへびドライ ",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is normal CoilSnake, but the translation still refers to it as Thirsty CoilSnake/Makihebi Dry and mentions "non-Mother 2" ROMs instead of "non-EarthBound ROMs." So submitting the translation as-is might not work, especially before CoilSnake even gets Mother 2 support...

Comment thread coilsnake/ui/language.py
Comment on lines +38 to +51
@staticmethod
def _json_to_translations(json_data):
missing = "Missing localization string"
return defaultdict(lambda: missing, json_data)

@classmethod
def _load_language(cls, language: Language):
try:
with open(language.get_json_path(), "r", encoding="utf-8") as file:
json_data = json.load(file)
return cls._json_to_translations(json_data)
except:
return None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand this correctly, this will make all missing strings in a JSON file say Missing localization string? This could work, but it seems like a lot of existing software tries to display the original language's string if a translation can't be found. There's no perfect solution here obviously, just wanted to start a discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants