Merge pull request #5924 from electron/chrome-i18n-get-message
Implement chrome.i18n.getMessage
This commit is contained in:
commit
50f5025447
8 changed files with 106 additions and 2 deletions
|
@ -63,6 +63,7 @@
|
|||
'lib/renderer/api/remote.js',
|
||||
'lib/renderer/api/screen.js',
|
||||
'lib/renderer/api/web-frame.js',
|
||||
'lib/renderer/extensions/i18n.js',
|
||||
],
|
||||
'js2c_sources': [
|
||||
'lib/common/asar.js',
|
||||
|
|
|
@ -115,6 +115,10 @@ ipcMain.on('CHROME_RUNTIME_CONNECT', function (event, extensionId, connectInfo)
|
|||
page.webContents.sendToAll(`CHROME_RUNTIME_ONCONNECT_${extensionId}`, event.sender.id, portId, connectInfo)
|
||||
})
|
||||
|
||||
ipcMain.on('CHROME_I18N_MANIFEST', function (event, extensionId) {
|
||||
event.returnValue = manifestMap[extensionId]
|
||||
})
|
||||
|
||||
ipcMain.on('CHROME_RUNTIME_SENDMESSAGE', function (event, extensionId, message) {
|
||||
const page = backgroundPages[extensionId]
|
||||
if (!page) {
|
||||
|
|
|
@ -199,4 +199,6 @@ exports.injectTo = function (extensionId, isBackgroundPage, context) {
|
|||
setPopup () {},
|
||||
getPopup () {}
|
||||
}
|
||||
|
||||
chrome.i18n = require('./extensions/i18n.js').setup(extensionId)
|
||||
}
|
||||
|
|
84
lib/renderer/extensions/i18n.js
Normal file
84
lib/renderer/extensions/i18n.js
Normal file
|
@ -0,0 +1,84 @@
|
|||
// Implementation of chrome.i18n.getMessage
|
||||
// https://developer.chrome.com/extensions/i18n#method-getMessage
|
||||
//
|
||||
// Does not implement predefined messages:
|
||||
// https://developer.chrome.com/extensions/i18n#overview-predefined
|
||||
|
||||
const {ipcRenderer} = require('electron')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
let metadata
|
||||
|
||||
const getExtensionMetadata = (extensionId) => {
|
||||
if (!metadata) {
|
||||
metadata = ipcRenderer.sendSync('CHROME_I18N_MANIFEST', extensionId)
|
||||
}
|
||||
return metadata
|
||||
}
|
||||
|
||||
const getMessagesPath = (extensionId, language) => {
|
||||
const metadata = getExtensionMetadata(extensionId)
|
||||
const defaultLocale = metadata.default_locale || 'en'
|
||||
const localesDirectory = path.join(metadata.srcDirectory, '_locales')
|
||||
let messagesPath = path.join(localesDirectory, language, 'messages.json')
|
||||
if (!fs.statSyncNoException(messagesPath)) {
|
||||
messagesPath = path.join(localesDirectory, defaultLocale, 'messages.json')
|
||||
}
|
||||
return messagesPath
|
||||
}
|
||||
|
||||
const getMessages = (extensionId, language) => {
|
||||
try {
|
||||
const messagesPath = getMessagesPath(extensionId, language)
|
||||
return JSON.parse(fs.readFileSync(messagesPath)) || {}
|
||||
} catch (error) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
const getLanguage = () => {
|
||||
return navigator.language.replace(/-.*$/, '').toLowerCase()
|
||||
}
|
||||
|
||||
const replaceNumberedSubstitutions = (message, substitutions) => {
|
||||
return message.replace(/\$(\d+)/, (_, number) => {
|
||||
const index = parseInt(number, 10) - 1
|
||||
return substitutions[index] || ''
|
||||
})
|
||||
}
|
||||
|
||||
const replacePlaceholders = (message, placeholders, substitutions) => {
|
||||
if (typeof substitutions === 'string') {
|
||||
substitutions = [substitutions]
|
||||
}
|
||||
if (!Array.isArray(substitutions)) {
|
||||
substitutions = []
|
||||
}
|
||||
|
||||
if (placeholders) {
|
||||
Object.keys(placeholders).forEach((name) => {
|
||||
let {content} = placeholders[name]
|
||||
content = replaceNumberedSubstitutions(content, substitutions)
|
||||
message = message.replace(new RegExp(`\\$${name}\\$`, 'gi'), content)
|
||||
})
|
||||
}
|
||||
|
||||
return replaceNumberedSubstitutions(message, substitutions)
|
||||
}
|
||||
|
||||
const getMessage = (extensionId, messageName, substitutions) => {
|
||||
const messages = getMessages(extensionId, getLanguage())
|
||||
if (messages.hasOwnProperty(messageName)) {
|
||||
const {message, placeholders} = messages[messageName]
|
||||
return replacePlaceholders(message, placeholders, substitutions)
|
||||
}
|
||||
}
|
||||
|
||||
exports.setup = (extensionId) => {
|
||||
return {
|
||||
getMessage (messageName, substitutions) {
|
||||
return getMessage(extensionId, messageName, substitutions)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -865,6 +865,7 @@ describe('browser-window module', function () {
|
|||
ipcMain.once('answer', function (event, message) {
|
||||
assert.equal(message.runtimeId, 'foo')
|
||||
assert.equal(message.tabId, w.webContents.id)
|
||||
assert.equal(message.i18nString, 'foo - bar (baz)')
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
|
10
spec/fixtures/devtools-extensions/foo/_locales/en/messages.json
vendored
Normal file
10
spec/fixtures/devtools-extensions/foo/_locales/en/messages.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"foo": {
|
||||
"message": "foo - $BAZ$ ($2)",
|
||||
"placeholders": {
|
||||
"baz": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,8 @@
|
|||
<script>
|
||||
var message = JSON.stringify({
|
||||
runtimeId: chrome.runtime.id,
|
||||
tabId: chrome.devtools.inspectedWindow.tabId
|
||||
tabId: chrome.devtools.inspectedWindow.tabId,
|
||||
i18nString: chrome.i18n.getMessage('foo', ['bar', 'baz'])
|
||||
})
|
||||
var sendMessage = `require('electron').ipcRenderer.send('answer', ${message})`
|
||||
window.chrome.devtools.inspectedWindow.eval(sendMessage, function () {})
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"name": "foo",
|
||||
"version": "1.0",
|
||||
"devtools_page": "foo.html"
|
||||
"devtools_page": "foo.html",
|
||||
"default_locale": "en"
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue