Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 36 additions & 48 deletions interface/devtools/cookie-list.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,18 @@ <h1 class="container">Cookie-Editor</h1>
<label
class="menu-item switch"
for="advanced-toggle-all"
id="advanced-toggle-all-label"
>
Show Advanced
id="advanced-toggle-all-label">
<span data-i18n="showAdvanced">Show Advanced</span>
<label class="switch">
<input
type="checkbox"
id="advanced-toggle-all"
aria-describedby="advanced-toggle-all-label"
/>
aria-describedby="advanced-toggle-all-label" />
<span class="slider"></span>
</label>
</label>
<button class="menu-item" id="menu-all-options">
See All Options
<span data-i18n="seeAllOptions">See All Options</span>
<svg class="icon">
<use href="../sprites/solid.svg#external-link-alt"></use>
</svg>
Expand All @@ -54,8 +52,7 @@ <h1 class="container">Cookie-Editor</h1>
<button
class="panel-section-footer-button"
id="create-cookie"
type="button"
>
type="button">
<div>
<svg class="icon"><use href="../sprites/solid.svg#plus"></use></svg>
<div class="tooltip" role="tooltip">Add</div>
Expand All @@ -66,8 +63,7 @@ <h1 class="container">Cookie-Editor</h1>
<button
class="panel-section-footer-button danger"
id="delete-all-cookies"
type="button"
>
type="button">
<div>
<svg class="icon">
<use href="../sprites/solid.svg#trash"></use>
Expand All @@ -80,8 +76,7 @@ <h1 class="container">Cookie-Editor</h1>
<button
class="panel-section-footer-button"
id="import-cookies"
type="button"
>
type="button">
<div>
<svg class="icon">
<use href="../sprites/solid.svg#file-import"></use>
Expand All @@ -94,8 +89,7 @@ <h1 class="container">Cookie-Editor</h1>
<button
class="panel-section-footer-button"
id="export-cookies"
type="button"
>
type="button">
<div>
<svg class="icon">
<use href="../sprites/solid.svg#file-export"></use>
Expand All @@ -111,8 +105,7 @@ <h1 class="container">Cookie-Editor</h1>
<button
class="panel-section-footer-button"
id="return-list-add"
type="button"
>
type="button">
<div>
<svg class="icon">
<use href="../sprites/solid.svg#arrow-left"></use>
Expand All @@ -125,8 +118,7 @@ <h1 class="container">Cookie-Editor</h1>
<button
class="panel-section-footer-button primary"
id="save-create-cookie"
type="button"
>
type="button">
<div>
<svg class="icon"><use href="../sprites/solid.svg#save"></use></svg>
<div class="tooltip" role="tooltip">Add</div>
Expand All @@ -140,8 +132,7 @@ <h1 class="container">Cookie-Editor</h1>
<button
class="panel-section-footer-button"
id="return-list-import"
type="button"
>
type="button">
<div>
<svg class="icon">
<use href="../sprites/solid.svg#arrow-left"></use>
Expand All @@ -154,8 +145,7 @@ <h1 class="container">Cookie-Editor</h1>
<button
class="panel-section-footer-button primary"
id="save-import-cookie"
type="button"
>
type="button">
<div>
<svg class="icon">
<use href="../sprites/solid.svg#file-import"></use>
Expand All @@ -172,8 +162,7 @@ <h1 class="container">Cookie-Editor</h1>
<button
id="notification-dismiss"
aria-label="Dismiss Notification"
type="button"
>
type="button">
<svg class="icon"><use href="../sprites/solid.svg#times"></use></svg>
</button>
</div>
Expand All @@ -188,8 +177,7 @@ <h1 class="container">Cookie-Editor</h1>
class="header container"
tabindex="0"
role="button"
aria-expanded="false"
>
aria-expanded="false">
<svg class="icon arrow">
<use href="../sprites/solid.svg#angle-down"></use>
</svg>
Expand All @@ -201,8 +189,7 @@ <h1 class="container">Cookie-Editor</h1>
data-tooltip-left="Delete"
aria-label="Delete"
tabindex="-1"
type="button"
>
type="button">
<svg class="icon">
<use href="../sprites/solid.svg#trash"></use>
</svg>
Expand All @@ -216,8 +203,7 @@ <h1 class="container">Cookie-Editor</h1>
class="delete"
data-tooltip="Delete"
aria-label="Delete"
type="button"
>
type="button">
<svg class="icon">
<use href="../sprites/solid.svg#trash"></use>
</svg>
Expand All @@ -226,8 +212,7 @@ <h1 class="container">Cookie-Editor</h1>
class="save"
data-tooltip="Save"
aria-label="Save"
type="submit"
>
type="submit">
<svg class="icon">
<use href="../sprites/solid.svg#save"></use>
</svg>
Expand Down Expand Up @@ -259,8 +244,7 @@ <h1 class="container">Cookie-Editor</h1>
<input
name="expiration"
type="text"
class="input-expiration"
/>
class="input-expiration" />
</div>
<div>
<label class="label-sameSite">Same Site</label>
Expand All @@ -275,16 +259,14 @@ <h1 class="container">Cookie-Editor</h1>
<input
type="checkbox"
name="hostOnly"
class="input-hostOnly"
/>
class="input-hostOnly" />
Host Only
</label>
<label class="label-session">
<input
type="checkbox"
name="session"
class="input-session"
/>
class="input-session" />
Session
</label>
<label class="label-secure">
Expand All @@ -295,8 +277,7 @@ <h1 class="container">Cookie-Editor</h1>
<input
type="checkbox"
name="httpOnly"
class="input-httpOnly"
/>
class="input-httpOnly" />
Http Only
</label>
</div>
Expand All @@ -317,8 +298,7 @@ <h1 class="container">Cookie-Editor</h1>
class="json"
name="content"
id="content-import"
placeholder='JSON: &#10;[{"name":"Cookie","value":"text",[...]}] &#10;&#10;Header String: &#10;Cookie=text;Editor=yes &#10;&#10;Netscape: &#10;# Netscape HTTP Cookie File &#10;# [...] &#10;cookie-editor.com[...] Cookie text'
></textarea>
placeholder='JSON: &#10;[{"name":"Cookie","value":"text",[...]}] &#10;&#10;Header String: &#10;Cookie=text;Editor=yes &#10;&#10;Netscape: &#10;# Netscape HTTP Cookie File &#10;# [...] &#10;cookie-editor.com[...] Cookie text'></textarea>
</div>
</form>
</template>
Expand All @@ -337,28 +317,30 @@ <h1 class="container">Cookie-Editor</h1>
</template>

<template id="tmp-empty">
<p class="container" id="no-cookies">
<p class="container" id="no-cookies" data-i18n="noCookies">
This page does not have any cookies.
</p>
</template>

<template id="tmp-no-permission">
<div class="container" id="no-permission">
<div class="container" id="no-permission" data-i18n="noPermission">
You do not have the permission required to read the cookies for this
page.
<div>
Request permission for...
<span data-i18n="requestPermissionFor"
>Request permission for...</span
>
<div class="button-container">
<button
id="request-permission"
title="Request permission to read cookies for this site."
>
data-i18n="thisSite">
This site
</button>
<button
id="request-permission-all"
title="Request permission to read cookies for all sites."
>
data-i18n="allSites">
All sites
</button>
</div>
Expand All @@ -367,7 +349,10 @@ <h1 class="container">Cookie-Editor</h1>
</template>

<template id="tmp-permission-impossible">
<div class="container" id="permission-impossible">
<div
class="container"
id="permission-impossible"
data-i18n="permissionImpossible">
Cookie-Editor can't display cookies for this page.
</div>
</template>
Expand Down Expand Up @@ -404,5 +389,8 @@ <h3>Export As:</h3>
</div>
</div>
</template>

<script src="../lib/isPopup.js"></script>
<script type="module" src="../popup/cookie-list.js"></script>
</body>
</html>
80 changes: 80 additions & 0 deletions interface/lib/i18n/i18n.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import en from './locales/en.js';
import zh from './locales/zh.js';

/**
* Internationalization class for handling multi-language support
*/
class I18n {
/**
* Constructor
*/
constructor() {
this.locales = {
en,
zh,
};
this.currentLocale = this.getUserLocale();
}

/**
* Get user's browser language setting
* @return {string} User's language code
*/
getUserLocale() {
// Try to get language from browser settings
const browserLocale = navigator.language || navigator.userLanguage;
const languageCode = browserLocale.split('-')[0];

// Check if the language is supported
if (this.locales[languageCode]) {
return languageCode;
}

// Default to English
return 'en';
}

/**
* Set current language
* @param {string} locale Language code
* @return {boolean} Whether the language was set successfully
*/
setLocale(locale) {
if (this.locales[locale]) {
this.currentLocale = locale;
return true;
}
return false;
}

/**
* Get translated text
* @param {string} key Translation key
* @param {string} defaultValue Default value
* @return {string} Translated text
*/
t(key, defaultValue = key) {
const locale = this.locales[this.currentLocale];
return locale[key] || defaultValue;
Comment on lines +57 to +58
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The use of the logical OR operator || here can lead to incorrect behavior when a translation is an empty string (''). An empty string is a falsy value, so locale[key] || defaultValue would incorrectly fall back to the defaultValue (the translation key). An empty string can be a valid translation, for example, to intentionally hide a piece of text.

To fix this, you should check for the existence of the key in the locale object more explicitly.

Suggested change
const locale = this.locales[this.currentLocale];
return locale[key] || defaultValue;
const locale = this.locales[this.currentLocale];
return Object.prototype.hasOwnProperty.call(locale, key) ? locale[key] : defaultValue;

}

/**
* Get supported languages
* @return {string[]} List of supported language codes
*/
getSupportedLocales() {
return Object.keys(this.locales);
}

/**
* Get current language
* @return {string} Current language code
*/
getCurrentLocale() {
return this.currentLocale;
}
}

// Export singleton instance
const i18n = new I18n();
export default i18n;
Loading