Class OfficialLanguageFiles
Official language files -- the lang/* catalogues the framework and each module ship and write to
disk -- are owned by the framework (maintainer decision 2026-10-04). When one differs from the bundled
version, it is restored to the bundled version at every start, the previous file is kept as a backup,
and one log line tells the operator to customise by copying the official file under a new name and
selecting that name in plugins/UltiTools/config.yml. A custom-named file is the operator's and is
never written, replaced or backed up.
Internal to the framework; not module-facing API.
- Since:
- 6.3.0
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static final classLogs why a framework language file was not replaced; the file stays as it was in every case but one. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringSuffix of a backup:<file>.bak, then<file>.1.bak,<file>.2.bakand so on, so no backup name ends in a catalogue extension the loaders resolve (.json,.yml,.yaml) and an existing file is never overwritten.private static final Typeprivate static final com.google.gson.Gsonstatic final intUpper bound on backup names tried for one file, so a full directory cannot loop forever.static final StringFramework i18n key for the one line logged when an official language file is restored. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic FilecopyToFreshBackup(File file) Copiesfileto the first backup name that does not exist yet, never overwriting anything: a name is skipped when any file or link exists there, and the copy itself refuses an existing target, so a name taken in between is skipped too.private static booleancopyUnlessTaken(File file, File candidate) static LanguagereadFrameworkCustomFile(File dataFolder, String name, String officialCode, ClassLoader loader, Logger logger) Reads the operator's custom framework language file<dataFolder>/lang/<name>.json(#608).readJson(byte[] bytes) private static byte[]readResource(ClassLoader loader, String resourcePath) private static booleanprivate static FilesyncFrameworkFile(File file, byte[] bundled, File dataFolder, String resourcePath, Logger logger) syncFrameworkFiles(File dataFolder, List<String> codes, ClassLoader loader, Logger logger) Writes the framework's official language files to<dataFolder>/lang/so an operator can copy them, and restores any that differ from the bundled version (#608).
-
Field Details
-
RESTORED_LOG_KEY
Framework i18n key for the one line logged when an official language file is restored. Arguments: the restored file, the module (UltiToolsfor the framework's own files) and the backup.- See Also:
-
BACKUP_SUFFIX
Suffix of a backup:<file>.bak, then<file>.1.bak,<file>.2.bakand so on, so no backup name ends in a catalogue extension the loaders resolve (.json,.yml,.yaml) and an existing file is never overwritten.- See Also:
-
MAX_BACKUP_NAMES
public static final int MAX_BACKUP_NAMESUpper bound on backup names tried for one file, so a full directory cannot loop forever.- See Also:
-
GSON
private static final com.google.gson.Gson GSON -
DICTIONARY_TYPE
-
-
Constructor Details
-
OfficialLanguageFiles
private OfficialLanguageFiles()
-
-
Method Details
-
copyToFreshBackup
Copiesfileto the first backup name that does not exist yet, never overwriting anything: a name is skipped when any file or link exists there, and the copy itself refuses an existing target, so a name taken in between is skipped too. The original stays in place.- Parameters:
file- the official language file about to be restored- Returns:
- the backup created, or
nullwhen allMAX_BACKUP_NAMESnames are taken - Throws:
IOException- if the copy fails for any other reason
-
copyUnlessTaken
- Throws:
IOException
-
syncFrameworkFiles
public static List<File[]> syncFrameworkFiles(File dataFolder, List<String> codes, ClassLoader loader, Logger logger) Writes the framework's official language files to<dataFolder>/lang/so an operator can copy them, and restores any that differ from the bundled version (#608). For each code incodeswhoselang/<code>.jsonthe framework jar ships:- absent: written and recorded in the provenance record
<dataFolder>/.ultitools-resource-hashes.json; - byte-identical to the bundled version: not written (only a missing record is added);
- still the bytes an earlier release wrote (the record matches): replaced by the bundled version, without a backup -- nobody edited it;
- anything else -- edited in place, or written by something other than the framework: kept as a backup
under the first free
<name>.bak/<name>.N.bakname, then replaced by the bundled version and recorded, and reported to the caller, which logsRESTORED_LOG_KEYonce it has a language.
<code>.jsonare ever written, so an operator's custom-named file in the same folder is never written, replaced or backed up. The replacement is atomic and refuses a read-only or symbolic-link file (the operator pinned it), as for module language files. A failure for one file is logged and leaves that file as it was; the framework reads its official texts from its jar either way.- Parameters:
dataFolder- the framework's data folder,plugins/UltiToolscodes- the official language codes the framework shipsloader- the class loader that reads the framework jar'slang/resourceslogger- the framework logger- Returns:
- one
{file, backup}pair per restored file, incodesorder
- absent: written and recorded in the provenance record
-
syncFrameworkFile
private static File syncFrameworkFile(File file, byte[] bundled, File dataFolder, String resourcePath, Logger logger) throws IOException - Throws:
IOException
-
readFrameworkCustomFile
public static Language readFrameworkCustomFile(File dataFolder, String name, String officialCode, ClassLoader loader, Logger logger) Reads the operator's custom framework language file<dataFolder>/lang/<name>.json(#608). Read only: nothing in the framework ever writes, replaces or backs up a custom-named file. A name that is not a safe language-code token (Localized.isSafeLanguageCode(java.lang.String)) is never turned into a path, so it cannot name a file outsidelang/.A key whose custom value lost a placeholder relative to the bundled value of
officialCodeuses the bundled value, in memory, with one warning naming the file and the key, never either value (the module guard of #441/#524,UltiToolsPlugin.overrideLostPlaceholders(java.util.Map<java.lang.String, java.lang.String>, java.util.Map<java.lang.String, java.lang.String>, java.util.function.BiConsumer<java.lang.String, java.lang.String>); gate-1 review R1-2 of plan 17-69).- Parameters:
dataFolder- the framework's data foldername- the configured custom language nameofficialCode- the official language the name is based onloader- the class loader that reads the framework jar'slang/resourceslogger- the framework logger- Returns:
- the custom language, or
nullwhen the name is unsafe, the file does not exist or it cannot be read or parsed (the reason is logged)
-
readJson
-
readResource
- Throws:
IOException
-
replace
-