Localize HeliosLauncher UI using lang files (#301)
* First step to use Language .json file in ejs * i18n for landing.ejs * i18n for login.ejs * i18n for loginOptions.ejs * i18n for overlay.ejs * i18n for settings.ejs * i18n for waiting.ejs * i18n for welcome.ejs * langloader.js placeholder support * i18n for landing.js * i18n for login.js * i18n for overlay.js * i18n for settings.js * i18n for uibinder.js * i18n for uicore.js * remove html language replacement * use toml for i18n * Fix mojang/microsoft status icon is undefined * cascadable langloader * separate lang file for customization * move some placeholder text to _placeholder.toml * Update * Reduce package lock diff. * Remove another placeholder. * Checkbox does not require translation. * Icons don't need translation. * Leave placeholders inline. * Fix translation for news pages. * Remove more unneeded translations. --------- Co-authored-by: Daniel Scalzi <d_scalzi@yahoo.com>
This commit is contained in:
@@ -125,7 +125,7 @@ document.getElementById('launch_button').addEventListener('click', async e => {
|
||||
}
|
||||
} catch(err) {
|
||||
loggerLanding.error('Unhandled error in during launch process.', err)
|
||||
showLaunchFailure('Error During Launch', 'See console (CTRL + Shift + i) for more details.')
|
||||
showLaunchFailure(Lang.queryJS('landing.launch.failureTitle'), Lang.queryJS('landing.launch.failureText'))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -145,7 +145,7 @@ document.getElementById('avatarOverlay').onclick = async e => {
|
||||
|
||||
// Bind selected account
|
||||
function updateSelectedAccount(authUser){
|
||||
let username = 'No Account Selected'
|
||||
let username = Lang.queryJS('landing.selectedAccount.noAccountSelected')
|
||||
if(authUser != null){
|
||||
if(authUser.displayName != null){
|
||||
username = authUser.displayName
|
||||
@@ -165,14 +165,14 @@ function updateSelectedServer(serv){
|
||||
}
|
||||
ConfigManager.setSelectedServer(serv != null ? serv.rawServer.id : null)
|
||||
ConfigManager.save()
|
||||
server_selection_button.innerHTML = '\u2022 ' + (serv != null ? serv.rawServer.name : 'No Server Selected')
|
||||
server_selection_button.innerHTML = '• ' + (serv != null ? serv.rawServer.name : Lang.queryJS('landing.noSelection'))
|
||||
if(getCurrentView() === VIEWS.settings){
|
||||
animateSettingsTabRefresh()
|
||||
}
|
||||
setLaunchEnabled(serv != null)
|
||||
}
|
||||
// Real text is set in uibinder.js on distributionIndexDone.
|
||||
server_selection_button.innerHTML = '\u2022 Loading..'
|
||||
server_selection_button.innerHTML = '• ' + Lang.queryJS('landing.selectedServer.loading')
|
||||
server_selection_button.onclick = async e => {
|
||||
e.target.blur()
|
||||
await toggleServerSelection(true)
|
||||
@@ -201,16 +201,14 @@ const refreshMojangStatuses = async function(){
|
||||
for(let i=0; i<statuses.length; i++){
|
||||
const service = statuses[i]
|
||||
|
||||
const tooltipHTML = `<div class="mojangStatusContainer">
|
||||
<span class="mojangStatusIcon" style="color: ${MojangRestAPI.statusToHex(service.status)};">•</span>
|
||||
<span class="mojangStatusName">${service.name}</span>
|
||||
</div>`
|
||||
if(service.essential){
|
||||
tooltipEssentialHTML += `<div class="mojangStatusContainer">
|
||||
<span class="mojangStatusIcon" style="color: ${MojangRestAPI.statusToHex(service.status)};">•</span>
|
||||
<span class="mojangStatusName">${service.name}</span>
|
||||
</div>`
|
||||
tooltipEssentialHTML += tooltipHTML
|
||||
} else {
|
||||
tooltipNonEssentialHTML += `<div class="mojangStatusContainer">
|
||||
<span class="mojangStatusIcon" style="color: ${MojangRestAPI.statusToHex(service.status)};">•</span>
|
||||
<span class="mojangStatusName">${service.name}</span>
|
||||
</div>`
|
||||
tooltipNonEssentialHTML += tooltipHTML
|
||||
}
|
||||
|
||||
if(service.status === 'yellow' && status !== 'red'){
|
||||
@@ -243,14 +241,14 @@ const refreshServerStatus = async (fade = false) => {
|
||||
loggerLanding.info('Refreshing Server Status')
|
||||
const serv = (await DistroAPI.getDistribution()).getServerById(ConfigManager.getSelectedServer())
|
||||
|
||||
let pLabel = 'SERVER'
|
||||
let pVal = 'OFFLINE'
|
||||
let pLabel = Lang.queryJS('landing.serverStatus.server')
|
||||
let pVal = Lang.queryJS('landing.serverStatus.offline')
|
||||
|
||||
try {
|
||||
|
||||
const servStat = await getServerStatus(47, serv.hostname, serv.port)
|
||||
console.log(servStat)
|
||||
pLabel = 'PLAYERS'
|
||||
pLabel = Lang.queryJS('landing.serverStatus.players')
|
||||
pVal = servStat.players.online + '/' + servStat.players.max
|
||||
|
||||
} catch (err) {
|
||||
@@ -288,7 +286,7 @@ function showLaunchFailure(title, desc){
|
||||
setOverlayContent(
|
||||
title,
|
||||
desc,
|
||||
'Okay'
|
||||
Lang.queryJS('landing.launch.okay')
|
||||
)
|
||||
setOverlayHandler(null)
|
||||
toggleOverlay(true)
|
||||
@@ -304,7 +302,7 @@ function showLaunchFailure(title, desc){
|
||||
*/
|
||||
async function asyncSystemScan(effectiveJavaOptions, launchAfter = true){
|
||||
|
||||
setLaunchDetails('Checking system info..')
|
||||
setLaunchDetails(Lang.queryJS('landing.systemScan.checking'))
|
||||
toggleLaunchArea(true)
|
||||
setLaunchPercentage(0, 100)
|
||||
|
||||
@@ -317,30 +315,30 @@ async function asyncSystemScan(effectiveJavaOptions, launchAfter = true){
|
||||
// If the result is null, no valid Java installation was found.
|
||||
// Show this information to the user.
|
||||
setOverlayContent(
|
||||
'No Compatible<br>Java Installation Found',
|
||||
`In order to join WesterosCraft, you need a 64-bit installation of Java ${effectiveJavaOptions.suggestedMajor}. Would you like us to install a copy?`,
|
||||
'Install Java',
|
||||
'Install Manually'
|
||||
Lang.queryJS('landing.systemScan.noCompatibleJava'),
|
||||
Lang.queryJS('landing.systemScan.installJavaMessage', { 'major': effectiveJavaOptions.suggestedMajor }),
|
||||
Lang.queryJS('landing.systemScan.installJava'),
|
||||
Lang.queryJS('landing.systemScan.installJavaManually')
|
||||
)
|
||||
setOverlayHandler(() => {
|
||||
setLaunchDetails('Preparing Java Download..')
|
||||
setLaunchDetails(Lang.queryJS('landing.systemScan.javaDownloadPrepare'))
|
||||
toggleOverlay(false)
|
||||
|
||||
try {
|
||||
downloadJava(effectiveJavaOptions, launchAfter)
|
||||
} catch(err) {
|
||||
loggerLanding.error('Unhandled error in Java Download', err)
|
||||
showLaunchFailure('Error During Java Download', 'See console (CTRL + Shift + i) for more details.')
|
||||
showLaunchFailure(Lang.queryJS('landing.systemScan.javaDownloadFailureTitle'), Lang.queryJS('landing.systemScan.javaDownloadFailureText'))
|
||||
}
|
||||
})
|
||||
setDismissHandler(() => {
|
||||
$('#overlayContent').fadeOut(250, () => {
|
||||
//$('#overlayDismiss').toggle(false)
|
||||
setOverlayContent(
|
||||
'Java is Required<br>to Launch',
|
||||
`A valid x64 installation of Java ${effectiveJavaOptions.suggestedMajor} is required to launch.<br><br>Please refer to our <a href="https://github.com/dscalzi/HeliosLauncher/wiki/Java-Management#manually-installing-a-valid-version-of-java">Java Management Guide</a> for instructions on how to manually install Java.`,
|
||||
'I Understand',
|
||||
'Go Back'
|
||||
Lang.queryJS('landing.systemScan.javaRequired', { 'major': effectiveJavaOptions.suggestedMajor }),
|
||||
Lang.queryJS('landing.systemScan.javaRequiredMessage', { 'major': effectiveJavaOptions.suggestedMajor }),
|
||||
Lang.queryJS('landing.systemScan.javaRequiredDismiss'),
|
||||
Lang.queryJS('landing.systemScan.javaRequiredCancel')
|
||||
)
|
||||
setOverlayHandler(() => {
|
||||
toggleLaunchArea(false)
|
||||
@@ -385,7 +383,7 @@ async function downloadJava(effectiveJavaOptions, launchAfter = true) {
|
||||
effectiveJavaOptions.distribution)
|
||||
|
||||
if(asset == null) {
|
||||
throw new Error('Failed to find OpenJDK distribution.')
|
||||
throw new Error(Lang.queryJS('landing.downloadJava.findJdkFailure'))
|
||||
}
|
||||
|
||||
let received = 0
|
||||
@@ -400,7 +398,7 @@ async function downloadJava(effectiveJavaOptions, launchAfter = true) {
|
||||
if(!await validateLocalFile(asset.path, asset.algo, asset.hash)) {
|
||||
log.error(`Hashes do not match, ${asset.id} may be corrupted.`)
|
||||
// Don't know how this could happen, but report it.
|
||||
throw new Error('Downloaded JDK has bad hash, file may be corrupted.')
|
||||
throw new Error(Lang.queryJS('landing.downloadJava.javaDownloadCorruptedError'))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,7 +407,7 @@ async function downloadJava(effectiveJavaOptions, launchAfter = true) {
|
||||
remote.getCurrentWindow().setProgressBar(2)
|
||||
|
||||
// Wait for extration to complete.
|
||||
const eLStr = 'Extracting Java'
|
||||
const eLStr = Lang.queryJS('landing.downloadJava.extractingJava')
|
||||
let dotStr = ''
|
||||
setLaunchDetails(eLStr)
|
||||
const extractListener = setInterval(() => {
|
||||
@@ -431,7 +429,7 @@ async function downloadJava(effectiveJavaOptions, launchAfter = true) {
|
||||
ConfigManager.save()
|
||||
|
||||
clearInterval(extractListener)
|
||||
setLaunchDetails('Java Installed!')
|
||||
setLaunchDetails(Lang.queryJS('landing.downloadJava.javaInstalled'))
|
||||
|
||||
// TODO Callback hell
|
||||
// Refactor the launch functions
|
||||
@@ -456,7 +454,7 @@ async function dlAsync(login = true) {
|
||||
|
||||
const loggerLaunchSuite = LoggerUtil.getLogger('LaunchSuite')
|
||||
|
||||
setLaunchDetails('Loading server information..')
|
||||
setLaunchDetails(Lang.queryJS('landing.dlAsync.loadingServerInfo'))
|
||||
|
||||
let distro
|
||||
|
||||
@@ -465,7 +463,7 @@ async function dlAsync(login = true) {
|
||||
onDistroRefresh(distro)
|
||||
} catch(err) {
|
||||
loggerLaunchSuite.error('Unable to refresh distribution index.', err)
|
||||
showLaunchFailure('Fatal Error', 'Could not load a copy of the distribution index. See the console (CTRL + Shift + i) for more details.')
|
||||
showLaunchFailure(Lang.queryJS('landing.dlAsync.fatalError'), Lang.queryJS('landing.dlAsync.unableToLoadDistributionIndex'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -478,7 +476,7 @@ async function dlAsync(login = true) {
|
||||
}
|
||||
}
|
||||
|
||||
setLaunchDetails('Please wait..')
|
||||
setLaunchDetails(Lang.queryJS('landing.dlAsync.pleaseWait'))
|
||||
toggleLaunchArea(true)
|
||||
setLaunchPercentage(0, 100)
|
||||
|
||||
@@ -494,17 +492,17 @@ async function dlAsync(login = true) {
|
||||
|
||||
fullRepairModule.childProcess.on('error', (err) => {
|
||||
loggerLaunchSuite.error('Error during launch', err)
|
||||
showLaunchFailure('Error During Launch', err.message || 'See console (CTRL + Shift + i) for more details.')
|
||||
showLaunchFailure(Lang.queryJS('landing.dlAsync.errorDuringLaunchTitle'), err.message || Lang.queryJS('landing.dlAsync.errorDuringLaunchText'))
|
||||
})
|
||||
fullRepairModule.childProcess.on('close', (code, _signal) => {
|
||||
if(code !== 0){
|
||||
loggerLaunchSuite.error(`Full Repair Module exited with code ${code}, assuming error.`)
|
||||
showLaunchFailure('Error During Launch', 'See console (CTRL + Shift + i) for more details.')
|
||||
showLaunchFailure(Lang.queryJS('landing.dlAsync.errorDuringLaunchTitle'), Lang.queryJS('landing.dlAsync.seeConsoleForDetails'))
|
||||
}
|
||||
})
|
||||
|
||||
loggerLaunchSuite.info('Validating files.')
|
||||
setLaunchDetails('Validating file integrity..')
|
||||
setLaunchDetails(Lang.queryJS('landing.dlAsync.validatingFileIntegrity'))
|
||||
let invalidFileCount = 0
|
||||
try {
|
||||
invalidFileCount = await fullRepairModule.verifyFiles(percent => {
|
||||
@@ -513,14 +511,14 @@ async function dlAsync(login = true) {
|
||||
setLaunchPercentage(100)
|
||||
} catch (err) {
|
||||
loggerLaunchSuite.error('Error during file validation.')
|
||||
showLaunchFailure('Error During File Verification', err.displayable || 'See console (CTRL + Shift + i) for more details.')
|
||||
showLaunchFailure(Lang.queryJS('landing.dlAsync.errorDuringFileVerificationTitle'), err.displayable || Lang.queryJS('landing.dlAsync.seeConsoleForDetails'))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if(invalidFileCount > 0) {
|
||||
loggerLaunchSuite.info('Downloading files.')
|
||||
setLaunchDetails('Downloading files..')
|
||||
setLaunchDetails(Lang.queryJS('landing.dlAsync.downloadingFiles'))
|
||||
setLaunchPercentage(0)
|
||||
try {
|
||||
await fullRepairModule.download(percent => {
|
||||
@@ -529,7 +527,7 @@ async function dlAsync(login = true) {
|
||||
setDownloadPercentage(100)
|
||||
} catch(err) {
|
||||
loggerLaunchSuite.error('Error during file download.')
|
||||
showLaunchFailure('Error During File Download', err.displayable || 'See console (CTRL + Shift + i) for more details.')
|
||||
showLaunchFailure(Lang.queryJS('landing.dlAsync.errorDuringFileDownloadTitle'), err.displayable || Lang.queryJS('landing.dlAsync.seeConsoleForDetails'))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@@ -541,7 +539,7 @@ async function dlAsync(login = true) {
|
||||
|
||||
fullRepairModule.destroyReceiver()
|
||||
|
||||
setLaunchDetails('Preparing to launch..')
|
||||
setLaunchDetails(Lang.queryJS('landing.dlAsync.preparingToLaunch'))
|
||||
|
||||
const mojangIndexProcessor = new MojangIndexProcessor(
|
||||
ConfigManager.getCommonDirectory(),
|
||||
@@ -559,7 +557,7 @@ async function dlAsync(login = true) {
|
||||
const authUser = ConfigManager.getSelectedAccount()
|
||||
loggerLaunchSuite.info(`Sending selected account (${authUser.displayName}) to ProcessBuilder.`)
|
||||
let pb = new ProcessBuilder(serv, versionData, forgeData, authUser, remote.app.getVersion())
|
||||
setLaunchDetails('Launching game..')
|
||||
setLaunchDetails(Lang.queryJS('landing.dlAsync.launchingGame'))
|
||||
|
||||
// const SERVER_JOINED_REGEX = /\[.+\]: \[CHAT\] [a-zA-Z0-9_]{1,16} joined the game/
|
||||
const SERVER_JOINED_REGEX = new RegExp(`\\[.+\\]: \\[CHAT\\] ${authUser.displayName} joined the game`)
|
||||
@@ -604,7 +602,7 @@ async function dlAsync(login = true) {
|
||||
data = data.trim()
|
||||
if(data.indexOf('Could not find or load main class net.minecraft.launchwrapper.Launch') > -1){
|
||||
loggerLaunchSuite.error('Game launch failed, LaunchWrapper was not downloaded properly.')
|
||||
showLaunchFailure('Error During Launch', 'The main file, LaunchWrapper, failed to download properly. As a result, the game cannot launch.<br><br>To fix this issue, temporarily turn off your antivirus software and launch the game again.<br><br>If you have time, please <a href="https://github.com/dscalzi/HeliosLauncher/issues">submit an issue</a> and let us know what antivirus software you use. We\'ll contact them and try to straighten things out.')
|
||||
showLaunchFailure(Lang.queryJS('landing.dlAsync.errorDuringLaunchTitle'), Lang.queryJS('landing.dlAsync.launchWrapperNotDownloaded'))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -616,7 +614,7 @@ async function dlAsync(login = true) {
|
||||
proc.stdout.on('data', tempListener)
|
||||
proc.stderr.on('data', gameErrorListener)
|
||||
|
||||
setLaunchDetails('Done. Enjoy the server!')
|
||||
setLaunchDetails(Lang.queryJS('landing.dlAsync.doneEnjoyServer'))
|
||||
|
||||
// Init Discord Hook
|
||||
if(distro.rawDistribution.discord != null && serv.rawServerdiscord != null){
|
||||
@@ -633,7 +631,7 @@ async function dlAsync(login = true) {
|
||||
} catch(err) {
|
||||
|
||||
loggerLaunchSuite.error('Error during launch', err)
|
||||
showLaunchFailure('Error During Launch', 'Please check the console (CTRL + Shift + i) for more details.')
|
||||
showLaunchFailure(Lang.queryJS('landing.dlAsync.errorDuringLaunchTitle'), Lang.queryJS('landing.dlAsync.checkConsoleForDetails'))
|
||||
|
||||
}
|
||||
}
|
||||
@@ -740,7 +738,7 @@ let newsLoadingListener = null
|
||||
*/
|
||||
function setNewsLoading(val){
|
||||
if(val){
|
||||
const nLStr = 'Checking for News'
|
||||
const nLStr = Lang.queryJS('landing.news.checking')
|
||||
let dotStr = '..'
|
||||
nELoadSpan.innerHTML = nLStr + dotStr
|
||||
newsLoadingListener = setInterval(() => {
|
||||
@@ -955,7 +953,7 @@ function displayArticle(articleObject, index){
|
||||
text.style.display = text.style.display === 'block' ? 'none' : 'block'
|
||||
}
|
||||
})
|
||||
newsNavigationStatus.innerHTML = index + ' of ' + newsArr.length
|
||||
newsNavigationStatus.innerHTML = Lang.query('ejs.landing.newsNavigationStatus', {currentPage: index, totalPages: newsArr.length})
|
||||
newsContent.setAttribute('article', index-1)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user