Bugzilla – Attachment 169561 Details for
Bug 37472
Make plugins translatable
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 37472: Enable extraction of strings from plugins
Bug-37472-Enable-extraction-of-strings-from-plugin.patch (text/plain), 8.37 KB, created by
Matt Blenkinsop
on 2024-07-25 14:31:56 UTC
(
hide
)
Description:
Bug 37472: Enable extraction of strings from plugins
Filename:
MIME Type:
Creator:
Matt Blenkinsop
Created:
2024-07-25 14:31:56 UTC
Size:
8.37 KB
patch
obsolete
>From 6a7ba7b1e2dda75440055c706d205b79cca94b21 Mon Sep 17 00:00:00 2001 >From: Matt Blenkinsop <matt.blenkinsop@ptfs-europe.com> >Date: Wed, 17 Jul 2024 16:23:26 +0000 >Subject: [PATCH] Bug 37472: Enable extraction of strings from plugins > >This patch extends the existing gulpfile to enable extraction of strings from plugins using a --plugins flag. Strings are extracted to files inside the plugin directory to then be translated via pull requests >--- > gulpfile.js | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 167 insertions(+), 1 deletion(-) > >diff --git a/gulpfile.js b/gulpfile.js >index 7ec5df077fd..6398254a45a 100644 >--- a/gulpfile.js >+++ b/gulpfile.js >@@ -163,7 +163,6 @@ function getPoTasks () { > > return tasks; > } >-const poTypes = getPoTasks(); > > function po_extract_marc (type) { > return src(`koha-tmpl/*-tmpl/*/en/**/*${type}*`, { read: false, nocase: true }) >@@ -354,6 +353,171 @@ function po_update_installer () { return po_update_type('installer') } > function po_update_installer_marc21 () { return po_update_type('installer-MARC21') } > function po_update_installer_unimarc () { return po_update_type('installer-UNIMARC') } > >+const PLUGINS_BASE = "/kohadevbox/plugins"; >+const PLUGINS = [] >+ >+if (args.plugins) { >+ const identifyPluginFile = (file) => { >+ const pluginFile = fs.readFileSync(file, 'utf8') >+ const fileByLine = pluginFile.split(/\r?\n/) >+ >+ let pluginIdentified = false >+ fileByLine.forEach(line => { >+ if (line.includes("Koha::Plugins::Base")) { >+ pluginIdentified = true >+ } >+ }) >+ return pluginIdentified >+ } >+ >+ const collectPluginFiles = (fullPath) => { >+ let files = [] >+ fs.readdirSync(fullPath).forEach(file => { >+ const absolutePath = path.join(fullPath, file) >+ if (fs.statSync(absolutePath).isDirectory()) { >+ const filesFromNestedFolder = collectPluginFiles(absolutePath) >+ filesFromNestedFolder && filesFromNestedFolder.forEach(file => { >+ files.push(file) >+ }) >+ } else { >+ return files.push(absolutePath) >+ } >+ }) >+ return files >+ } >+ >+ function po_create_plugins(pluginData, type) { >+ const access = util.promisify(fs.access); >+ const exec = util.promisify(child_process.exec); >+ >+ const translatorDirCheck = fs.readdirSync(pluginData.bundlePath).includes('translator') >+ if (!translatorDirCheck) { >+ fs.mkdirSync(`${pluginData.bundlePath}/translator`) >+ } >+ const poDirCheck = fs.readdirSync(pluginData.bundlePath + '/translator').includes('po') >+ if (!poDirCheck) { >+ fs.mkdirSync(`${pluginData.bundlePath}/translator/po`) >+ } >+ >+ const pot = `${pluginData.bundlePath}/translator/${pluginData.name}-${type}.pot`; >+ >+ // Generate .pot only if it doesn't exist or --force-extract is given >+ const extract = () => stream.finished(poTasks[`${pluginData.name}-${type}`].extract()); >+ >+ const p = >+ args['generate-pot'] === 'always' ? extract() : >+ args['generate-pot'] === 'auto' ? access(pot).catch(extract) : >+ args['generate-pot'] === 'never' ? Promise.resolve(0) : >+ Promise.reject(new Error('Invalid value for option --generate-pot: ' + args['generate-pot'])) >+ >+ return p.then(function () { >+ const languages = getLanguages(); >+ const promises = []; >+ languages.forEach(language => { >+ const locale = language.split('-').filter(s => s.length !== 4).join('_'); >+ const po = `${pluginData.bundlePath}/translator/po/${language}-${pluginData.name}-${type}.po`; >+ >+ const promise = access(po) >+ .catch(() => exec(`msginit -o ${po} -i ${pot} -l ${locale} --no-translator`)) >+ promises.push(promise); >+ }) >+ return Promise.all(promises); >+ }) >+ } >+ >+ function po_extract_plugins_js(pluginData) { >+ const globs = [ >+ `${pluginData.directory}/**/*.js`, >+ `${pluginData.directory}/**/*.vue`, >+ `!${pluginData.directory}/**/node_modules/**/*`, >+ ]; >+ >+ return src(globs, { read: false, nocase: true }) >+ .pipe(xgettext(`xgettext -L JavaScript ${xgettext_options}`, `${pluginData.name}-js.pot`)) >+ .pipe(dest(`${pluginData.bundlePath}/translator`)) >+ } >+ >+ function po_extract_plugins_template(pluginData) { >+ const globs = [ >+ `${pluginData.directory}/**/*.tt`, >+ `${pluginData.directory}/**/*.inc`, >+ `!${pluginData.directory}/**/node_modules/**/*`, >+ ]; >+ >+ return src(globs, { read: false, nocase: true }) >+ .pipe(xgettext('misc/translator/xgettext.pl --charset=UTF-8 -F', `${pluginData.name}-template.pot`)) >+ .pipe(dest(`${pluginData.bundlePath}/translator`)) >+ } >+ >+ function po_update_plugins(pluginData, type) { >+ const access = util.promisify(fs.access); >+ const exec = util.promisify(child_process.exec); >+ >+ const pot = `${pluginData.bundlePath}/translator/${pluginData.name}-${type}.pot`; >+ >+ // Generate .pot only if it doesn't exist or --force-extract is given >+ const extract = () => stream.finished(poTasks[`${pluginData.name}-${type}`].extract()); >+ const p = >+ args['generate-pot'] === 'always' ? extract() : >+ args['generate-pot'] === 'auto' ? access(pot).catch(extract) : >+ args['generate-pot'] === 'never' ? Promise.resolve(0) : >+ Promise.reject(new Error('Invalid value for option --generate-pot: ' + args['generate-pot'])) >+ >+ return p.then(function () { >+ const languages = getLanguages(); >+ const promises = []; >+ languages.forEach(language => { >+ const po = `${pluginData.bundlePath}/translator/po/${language}-${pluginData.name}-${type}.po`; >+ promises.push(exec(`msgmerge --backup=off --no-wrap --quiet -F --update ${po} ${pot}`)); >+ }) >+ >+ return Promise.all(promises); >+ }); >+ } >+ >+ // Remove all tasks except for plugins >+ Object.keys(poTasks).forEach(task => { >+ delete poTasks[task] >+ }) >+ >+ const pluginNames = fs.readdirSync(PLUGINS_BASE); >+ pluginNames.forEach(plugin => { >+ const pluginFiles = collectPluginFiles(`${PLUGINS_BASE}/${plugin}/Koha`) >+ let pluginFilePath >+ pluginFiles.forEach(file => { >+ const pluginFile = identifyPluginFile(file) >+ if (pluginFile) { >+ pluginFilePath = file.split('.')[0] >+ } >+ }) >+ const name = pluginFilePath.split('/').pop() >+ const pluginData = { >+ name, >+ bundlePath: pluginFilePath, >+ directory: `${PLUGINS_BASE}/${plugin}`, >+ } >+ PLUGINS.push(pluginData) >+ >+ function po_extract_js () { return po_extract_plugins_js(pluginData) } >+ function po_create_js () { return po_create_plugins(pluginData, 'js') } >+ function po_update_js () { return po_update_plugins(pluginData, 'js') } >+ function po_extract_template () { return po_extract_plugins_template(pluginData) } >+ function po_create_template () { return po_create_plugins(pluginData, 'template') } >+ function po_update_template () { return po_update_plugins(pluginData, 'template') } >+ >+ poTasks[`${name}-js`] = { >+ extract: po_extract_js, >+ create: po_create_js, >+ update: po_update_js, >+ } >+ poTasks[`${name}-template`] = { >+ extract: po_extract_template, >+ create: po_create_template, >+ update: po_update_template, >+ } >+ }) >+} >+ > /** > * Gulp plugin that executes xgettext-like command `cmd` on all files given as > * input, and then outputs the result as a POT file named `filename`. >@@ -434,6 +598,8 @@ if (args['_'][0].match("po:") && !fs.existsSync('misc/translator/po')) { > process.exit(1); > } > >+const poTypes = getPoTasks(); >+ > exports['po:create'] = parallel(...poTypes.map(type => poTasks[type].create)); > exports['po:update'] = parallel(...poTypes.map(type => poTasks[type].update)); > exports['po:extract'] = parallel(...poTypes.map(type => poTasks[type].extract)); >-- >2.39.3 (Apple Git-146)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 37472
: 169561 |
169562
|
169563
|
169564