Skip to content

Commit 726b266

Browse files
rpatters1asherber
andauthored
Localization (#649)
* add auto-width tester * auto resize width sample * refinements * add ComboBox to mixin, plus sample * lint fix and sample update * add other auto-layout features * sample auto_layout updates * auto-layout sample for 0.71 * revise auto-layout demo script * fix issue with FCMCtrlCheckBox not storing state * add 3-state checkbox for testing * fix text * add localization demo * refactor localization to add the localization tables to the library itself. * localize menu options of Transpose By Steps * docs, tranposition localization * localization of transpose * fix a few typos * make compatible with JW Lua * fix typo * Fix typos in Spanish text. * localized enharmonic transposition scripts * refinements to localization * add localization for chromatic transpose * refinements to localizing transposition * auto_layout changes for latest RGP Lua dev branch * Add mixin version of `__FCUserWindow::CreateChildUI` for backwards compatibility with JW Lua. * update finenv with latest info * one more lint warning * transpose_by_step is working * transpose_chromatic * enharmonic transposing * lint errors * refactor folder layout for localization * clarify comments * checkpoint localization tool * checkpoint localization tool * localization tool semi-working. main things missing are plugindef support and async openai calls * refactor sync openai calls to async * line ending * plugindef localization kind of working * plugindef localization is working * localize an example with a lot of additional menu items * Add script group name and description * minor updates * Added table to list of types recognized by AddStrings method. Other mods to take advantage of this. * refactor mixins per suggestions from ThistleSifter * a word * update sample localized script with latest approaches * Bundle localizations * address code review issues. * in-progress checkpoint for Base localization. * Base localization added to all src scripts and utilities. Still need to work on format strings. * auto_layout.lua code complete * update with latest agreed changes * fix lint error * add table support for multi-string arguments methods. * changed `process_string_arguments` to `create_multi_string_proxy` so that errors are reported at the correct level, rather than in `tryfunczzz`. * remove mobdebug * fix small issues discovered * Changes for `*AutoLocalized` mixin functions. --------- Co-authored-by: Aaron Sherber <[email protected]>
1 parent c2fb8e4 commit 726b266

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2233
-253
lines changed

.github/actions/bundle/dist/index.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -6791,12 +6791,13 @@ const importFileBase = (name, importedFiles, fetcher) => {
67916791
}
67926792
};
67936793
exports.importFileBase = importFileBase;
6794-
const bundleFileBase = (name, importedFiles, mixins, fetcher) => {
6794+
const bundleFileBase = (name, importedFiles, mixins, localizations, fetcher) => {
67956795
var _a;
67966796
const fileContents = (0, inject_extras_1.injectExtras)(name, fetcher(name));
67976797
const fileStack = [fileContents];
67986798
const importStack = (0, helpers_1.getAllImports)(fileContents);
67996799
const importedFileNames = new Set();
6800+
importStack.push(...localizations);
68006801
while (importStack.length > 0) {
68016802
const nextImport = (_a = importStack.pop()) !== null && _a !== void 0 ? _a : '';
68026803
if (importedFileNames.has(nextImport))
@@ -6821,7 +6822,16 @@ const bundleFileBase = (name, importedFiles, mixins, fetcher) => {
68216822
};
68226823
exports.bundleFileBase = bundleFileBase;
68236824
const bundleFile = (name, sourcePath, mixins) => {
6824-
const bundled = (0, exports.bundleFileBase)(name, exports.files, mixins, (fileName) => fs_1.default.readFileSync(path_1.default.join(sourcePath, fileName)).toString());
6825+
const localizations = [];
6826+
const baseName = path_1.default.basename(name, '.lua');
6827+
const locPath = path_1.default.join(sourcePath, 'localization', baseName);
6828+
if (fs_1.default.existsSync(locPath)) {
6829+
localizations.push(...fs_1.default
6830+
.readdirSync(locPath)
6831+
.filter(fileName => fileName.endsWith('.lua'))
6832+
.map(file => `localization.${baseName}.${path_1.default.basename(file, '.lua')}`));
6833+
}
6834+
const bundled = (0, exports.bundleFileBase)(name, exports.files, mixins, localizations, (fileName) => fs_1.default.readFileSync(path_1.default.join(sourcePath, fileName)).toString());
68256835
const parts = (0, helpers_1.getFileParts)(bundled);
68266836
return (0, remove_comments_1.removeComments)(parts.prolog, true)
68276837
+ (0, remove_comments_1.removeComments)(parts.plugindef, false)

.github/actions/bundle/src/bundle.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ describe('bundle', () => {
4040
}
4141

4242
it('bundleFile', () => {
43-
const bundle = bundleFileBase('a.lua', {}, [], fetcher)
43+
const bundle = bundleFileBase('a.lua', {}, [], [], fetcher)
4444
expect(bundle).toBe(
4545
[
4646
'package.preload["b"] = package.preload["b"] or function()',
@@ -58,17 +58,17 @@ describe('bundle', () => {
5858
})
5959

6060
it('bundleFile with no imports', () => {
61-
const bundle = bundleFileBase('c.lua', {}, [], fetcher)
61+
const bundle = bundleFileBase('c.lua', {}, [], [], fetcher)
6262
expect(bundle).toBe('return {}')
6363
})
6464

6565
it('ignore unresolvable imports', () => {
66-
const bundle = bundleFileBase('invalid.lua', {}, [], fetcher)
66+
const bundle = bundleFileBase('invalid.lua', {}, [], [], fetcher)
6767
expect(bundle).toBe(["local invalid = require('invalid.import')"].join('\n'))
6868
})
6969

7070
it('imports all mixins', () => {
71-
const bundle = bundleFileBase('mixin.lua', {}, ['mixin.FCMControl', 'mixin.FCMString'], fetcher)
71+
const bundle = bundleFileBase('mixin.lua', {}, ['mixin.FCMControl', 'mixin.FCMString'], [], fetcher)
7272
expect(bundle).toBe(
7373
[
7474
'package.preload["mixin.FCMControl"] = package.preload["mixin.FCMControl"] or function()',

.github/actions/bundle/src/bundle.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,16 @@ export const bundleFileBase = (
3333
name: string,
3434
importedFiles: ImportedFiles,
3535
mixins: string[],
36+
localizations: string[],
3637
fetcher: (name: string) => string
3738
) => {
3839
const fileContents = injectExtras(name, fetcher(name))
3940
const fileStack: string[] = [fileContents]
4041
const importStack: string[] = getAllImports(fileContents)
4142
const importedFileNames = new Set<string>()
4243

44+
importStack.push(...localizations)
45+
4346
while (importStack.length > 0) {
4447
const nextImport = importStack.pop() ?? ''
4548
if (importedFileNames.has(nextImport)) continue
@@ -63,7 +66,18 @@ export const bundleFileBase = (
6366
}
6467

6568
export const bundleFile = (name: string, sourcePath: string, mixins: string[]): string => {
66-
const bundled: string = bundleFileBase(name, files, mixins, (fileName: string) =>
69+
const localizations: string[] = []
70+
const baseName = path.basename(name, '.lua')
71+
const locPath = path.join(sourcePath, 'localization', baseName)
72+
if (fs.existsSync(locPath)) {
73+
localizations.push(...fs
74+
.readdirSync(locPath)
75+
.filter(fileName => fileName.endsWith('.lua'))
76+
.map(file => `localization.${baseName}.${path.basename(file, '.lua')}`)
77+
)
78+
}
79+
80+
const bundled: string = bundleFileBase(name, files, mixins, localizations, (fileName: string) =>
6781
fs.readFileSync(path.join(sourcePath, fileName)).toString()
6882
);
6983
const parts = getFileParts(bundled);

.github/actions/bundle/tsconfig.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
"module": "commonjs",
1515
"moduleResolution": "node",
1616
"resolveJsonModule": true,
17-
"declaration": false
17+
"declaration": false,
18+
"outDir": "dist",
19+
"sourceMap": true
1820
},
1921
"include": [
2022
"**/*.ts",

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,6 @@ dist/**/personal*
3030
# (finale_lua_menus.txt is the menu layout file used by finale_lua_menu_organizer.lua)
3131
finale_lua_menus.txt
3232

33+
.github/**/dist/*.js
34+
!.github/**/dist/index.js
35+
.github/**/dist/*.map

.luacheckrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-- luacheck: ignore 131
2-
include_files = { "src/**/*.lua", "samples/**/*.lua"}
2+
include_files = { "src/**/*.lua", "samples/**/*.lua", "utilities/**/*.lua"}
33
exclude_files = {
44
"mobdebug.lua",
55
}

.vscode/recommended_settings.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,17 @@
1414
"loadall",
1515
"loadallforregion",
1616
"pairsbykeys",
17+
"prettyformatjson",
1718
"bit32",
1819
"utf8",
1920
"socket",
2021
"tinyxml2",
2122
"xmlelements",
22-
"xmlattributes",
23-
"prettyformatjson"
23+
"xmlattributes"
2424
],
2525
"files.exclude": {
2626
"mobdebug.lua": true,
27+
"dist/**": true
2728
},
2829
"editor.formatOnSave": true,
2930
"Lua.diagnostics.enable": false,

docs/rgp-lua.md

+31-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ print ("Hello, world!")
1717
If you want a “Hello, world!” example that shows up as a menu option in Finale's Plug-in menu, here is a slightly more complex version:
1818

1919
```lua
20-
function plugindef()
20+
function plugindef(locale)
2121
return "Hello World", "Hello World", 'Displays a message box saying, "Hello, world!"'
2222
end
2323

@@ -285,7 +285,6 @@ The `plugindef()` function is an optional function that **only** should do a _ma
285285
* Return the _plug-in name_, _undo string_ and _brief description_ to be used in the _Finale_ plug-in menu and for automatic undo blocks.
286286
* Define the `finaleplugin` namespace environment to further describe the plug-in (see below).
287287

288-
289288
A simple `plugindef()` implementation might look like this:
290289

291290
```lua
@@ -296,7 +295,36 @@ function plugindef()
296295
end
297296
```
298297

299-
`plugindef()` is considered to be a reserved name in the global namespace. If the script has a function named `plugindef()`, the Lua plugin may call it at any time (not only during script execution) to gather information about the plug-in. The `plugindef()` function can **NOT** have dependencies outside the function itself.
298+
Starting with version 0.71, _RGP Lua_ passes the user's locale code as an argument to the `plugindef` function. You can use this to localize any strings returned by the function or assigned to variables. The user's locale code is a 2-character lowercase language code followed by "_" or "-" and then a 2-digit uppercase region code. This is the same value that is returned by `finenv.UI():GetUserLocaleName()`. (See the note below detailing why the `plugindef` function cannot call `GetUserLocaleName` directly.)
299+
300+
A localized version of the same function might look like this:
301+
302+
```lua
303+
function plugindef(locale)
304+
finaleplugin.RequireSelection = true
305+
finaleplugin.CategoryTags = "Rest, Region"
306+
local localization = {}
307+
localization.en = {
308+
menu = "Hide Rests",
309+
desc = "Hides all rests in the selected region."
310+
}
311+
localization.es = {
312+
menu = "Ocultar Silencios",
313+
desc = "Oculta todos los silencios en la región seleccionada."
314+
}
315+
localization.jp = {
316+
menu = "休符を隠す",
317+
desc = "選択した領域内のすべての休符を隠します。",
318+
}
319+
-- add more localizations as desired
320+
local t = locale and localization[locale:sub(1,2)] or localization.en
321+
return t.menu, t.menu, t.desc
322+
end
323+
```
324+
325+
Note that the `plugindef()` function must be *entirely* self-contained. It may not have access to any of the global namespaces that the rest of the script uses, such as `finenv` or `finale`. It *does* have access to all the standard Lua libraries. If the script has a function named `plugindef()`, the Lua plugin may call it at any time (not only during script execution) to gather information about the plug-in.
326+
327+
`plugindef` is a reserved name in the global namespace.
300328

301329
All aspects of the `plugindef()` are optional, but for a plug-in script that is going to be used repeatedly, the minimum should be to return a plug-in name, undo string, and short description.
302330

docs/rgp-lua/finenv-properties.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -245,22 +245,23 @@ end
245245

246246
A list of constants that define the type of message returned by `finenv.ExecuteLuaScriptItem` (if any).
247247

248-
- `SCRIPT_RESULT` : The message was returned by Lua. It could be either an error or a value returned by the script. If it is an error, the first value returned by `ExecuteLuaScriptItem` is false.|
248+
- `SCRIPT_RESULT` : The message was returned by the Lua script. This is not an error message.
249249
- `DOCUMENT_REQUIRED` : The script was not executed because it specified `finaleplugin.RequireDocument = true` but no document was open.
250250
- `SELECTION_REQUIRED` : The script was not executed because it specified `finaleplugin.RequireSelection = true` but there was no selection.
251251
- `SCORE_REQUIRED` : The script was not executed because it specified `finaleplugin.RequireScore = true` but the document was viewing a part.
252252
- `FINALE_VERSION_MISMATCH` : The script was not executed because it specified a minimum or maximum Finale version and the current running version of Finale does not meet the requirement.
253253
- `LUA_PLUGIN_VERSION_MISMATCH` : The script was not executed because it specified a minimum or maximum Lua plugin version and the current running version of _RGP Lua_ does not meet the requirement.
254254
- `MISCELLANEOUS` : Other types of error messages that do not fit any of the other categories.
255255
- `EXTERNAL_TERMINATION` : The script was externally terminated by the user or a controlling script.
256+
- `LUA_ERROR` : The message is an error message returned by Lua.
256257

257258
Example:
258259

259260
```lua
260261
local scripts = finenv.CreateLuaScriptItems()
261262
local success, error_msg, msg_type = finenv.ExecuteLuaScriptItem(scripts:GetItemAt(0))
262263
if not success then
263-
if msg_type == finenv.MessageResultType.SCRIPT_RESULT then
264+
if msg_type == finenv.MessageResultType.LUA_ERROR then
264265
-- take some action
265266
end
266267
end

0 commit comments

Comments
 (0)