Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

If you have any questions, reports, suggestions, or requests about Live2D, please send them to this forum.
※We cannot guarantee statements or answers from Live2D staff. Thank you for your understanding in advance.
 
Live2D Cubism
Cubism Products and Downloads
Cubism product manuals and tutorials
Cubism Editor Manual    Cubism Editor Tutorial    Cubism SDK Manual    Cubism SDK Tutorial
[About macOS Sequoia] (Updated October 22, 2024)
Live2D Cubism Editor 5.1.02 now supports macOS Sequoia.
Other Live2D Cubism products currently released are not guaranteed to work on macOS Sequoia.
Please refrain from upgrading macOS, as it may not operate properly.

[Feature Request] Support for community translations

Live2D Cubism is getting increasingly popular ouside of east asian and english speaking countries.
Sadly, there is currently no simple way to add custom translations.
So, I propose to provide a folder (%AppData%/translations) that can be used as an overlay for localized strings of the user interface.

This has the following benefits:
  • The community could provide community-contributed translations (no official support required)
  • Translations could grow incrementally and could be improved without the need for modifying the application
  • Users could customize the text of the user interface according to their needs
The required modifications amount to roughly 100 lines of code and are only local to the class i18n_code.I18N_core.
Example code:

public final @NonNull String getText(@NonNull String str, @NonNull String... strArr) {
...

if (communityMap == null) {
final File translationsFolder = new File(jp.noids.util.Paths.getUserDataPath() + File.separator + "translations");
communityMap = loadMap(translationsFolder, "I18N_core3");
communityMap.putAll(loadMap(translationsFolder, "I18N_cubism3"));
communityMap.putAll(loadMap(translationsFolder, "cubism21/I18N_cn_cubism_proto"));
communityMap.putAll(loadMap(translationsFolder, "cubism21/I18N_cn_lib_core"));
communityMap.putAll(loadMap(translationsFolder, "cubism21/I18N_cn_lib_design"));
communityMap.putAll(loadMap(translationsFolder, "cubism21/I18N_cn_lib_flash"));
communityMap.putAll(loadMap(translationsFolder, "cubism21/I18N_cn_lib_image"));
communityMap.putAll(loadMap(translationsFolder, "cubism21/I18N_cn_lib_movie"));
}

String result = communityMap.get(str);
if (result == null) {
result = map.get(str);
}
if (result == null) {
result = findInOldMap(str);
}
...
}

private final @NonNull HashMap loadMap(@NonNull File directory, @NonNull String path) {
if (!directory.isDirectory()) {
return new HashMap<>();
}

Locale locale = Locale.getDefault();
Intrinsics.checkExpressionValueIsNotNull(locale, "Locale.getDefault()");

List split = new Regex("\n").split(loadResourceFile(directory, path, locale.getLanguage()), 0);
List list = CollectionsKt.emptyList();
if (!split.isEmpty()) {
ListIterator listIterator = split.listIterator(split.size());
while (listIterator.hasPrevious()) {
if (!(((String) listIterator.previous()).length() == 0)) {
list = CollectionsKt.take(split, listIterator.nextIndex() + 1);
break;
}
}
}

String[] lines = list.toArray(new String[0]);
HashMap hashMap = new HashMap<>();
for (String line : lines) {
int index = StringsKt.indexOf(line, SEPARATOR, 0, false);
if (index > 0) {
hashMap.put(line.substring(0, index), decode(line.substring(index + 1)));
}
}

return hashMap;
}

private final @NonNull String loadResourceFile(@NonNull File directory, @NonNull String path, @NonNull String locale) {
String resourceData = "";

try {
File basePath = new File(directory + File.separator + String.format("%s.txt", path));
if (basePath.isFile()) {
resourceData = resourceData + UtURL.readText(basePath.toURI().toURL(), "UTF-8");
}

if (locale != null && !Intrinsics.areEqual("en", locale)) {
File localePath = new File(directory + File.separator + String.format("%s_%s.txt", path, locale));
if (localePath.isFile()) {
resourceData = resourceData + UtURL.readText(localePath.toURI().toURL(), "UTF-8");
}
}
} catch (MalformedURLException e) {
e.printStackTrace(System.err);
}

return resourceData;
}

Comments

Sign In or Register to comment.