Skip to content
Merged
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
30 changes: 30 additions & 0 deletions .github/workflows/sync-locales.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Sync Crowdin locales

on:
workflow_dispatch:
push:
branches: [ cosine ]

jobs:
synchronize-with-crowdin:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: crowdin action
uses: crowdin/github-action@v2
with:
upload_sources: true
upload_translations: false
download_translations: true
localization_branch_name: l10n_cosine
create_pull_request: true
pull_request_title: 'New Crowdin updates'
pull_request_body: 'New Crowdin translations and locales. (automated)'
pull_request_base_branch_name: 'cosine'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
8 changes: 8 additions & 0 deletions crowdin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
base_path: locales
files:
- source: en-US/sine-preferences.ftl
translation: sine-preferences.ftl
- source: en-US/sine-toasts.ftl
translation: sine-toasts.ftl
- source: en-US/sine-cmdpalette.ftl
translation: sine-cmdpalette.ftl
Binary file modified deployment/engine.zip
Binary file not shown.
2 changes: 1 addition & 1 deletion engine.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"profilePath": "profile.zip",
"updates": [
{
"version": "2.3",
"version": "2.3.0.3",
"updateBoot": true
}
]
Expand Down
106 changes: 63 additions & 43 deletions engine/utils/dom.mjs
Original file line number Diff line number Diff line change
@@ -1,52 +1,55 @@
const parseMD = (element, markdown, relativeURL, window = window) => {
const document = window.document;
const parseMD = (element, markdown, relativeURL, windowObj = window) => {
const document = windowObj.document;

if (!document.querySelector('link[href*="marked_styles.css"]')) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.className = "marked-styles";
link.href = "chrome://userscripts/content/engine/assets/imports/marked_styles.css";
document.head.appendChild(link);
}

if (!document.querySelector("style.marked-styles")) {
appendXUL(
document.head,
'<link rel="stylesheet" href="chrome://userscripts/content/engine/assets/imports/marked_styles.css"/>'
if (!windowObj.marked) {
Services.scriptloader.loadSubScriptWithOptions(
"chrome://userscripts/content/engine/assets/imports/marked_parser.js",
{ target: windowObj }
);
}

Services.scriptloader.loadSubScriptWithOptions(
"chrome://userscripts/content/engine/assets/imports/marked_parser.js",
{ target: window }
);
const renderer = new windowObj.marked.Renderer();

const renderer = new window.marked.Renderer();
const fixURL = (href) => {
if (/^(https?:\/\/|\/\/)/i.test(href)) return href;
return `${relativeURL.replace(/\/$/, "")}/${href.replace(/^\//, "")}`;
};

renderer.image = (href, title, text) => {
if (!href.match(/^https?:\/\//) && !href.startsWith("//")) href = `${relativeURL}/${href}`;
const titleAttr = title ? `title="${title}"` : "";
return `<img src="${href}" alt="${text}" ${titleAttr} />`;
const titleAttr = title ? ` title="${title}"` : "";
return `<img src="${fixURL(href)}" alt="${text}"${titleAttr} />`;
};

renderer.link = (href, title, text) => {
if (!href.match(/^https?:\/\//) && !href.startsWith("//")) {
let finalHref = href;
if (!/^(https?:\/\/|\/\/)/i.test(href)) {
const isRelativePath = href.includes("/") || /\.(md|html|htm|png|jpg|jpeg|gif|svg|pdf)$/i.test(href);
if (isRelativePath) href = `${relativeURL}/${href}`;
else href = `https://${href}`;
finalHref = isRelativePath ? fixURL(href) : `https://${href}`;
}
const titleAttr = title ? `title="${title}"` : "";
return `<a href="${href}" ${titleAttr}>${text}</a>`;
const titleAttr = title ? ` title="${title}"` : "";
return `<a href="${finalHref}"${titleAttr}>${text}</a>`;
};

window.marked.setOptions({
windowObj.marked.setOptions({
gfm: true,
renderer: renderer,
});

element.innerHTML = window.marked.parse(markdown).replace(/<(img|hr|br|input)([^>]*?)(?<!\/)>/gi, "<$1$2 />");

delete window.marked;
element.innerHTML = windowObj.marked.parse(markdown).replace(/<(img|hr|br|input)([^>]*?)(?<!\/)>/gi, "<$1$2 />");
};

const appendXUL = (parentElement, xulString, insertBefore = null, XUL = false) => {
let element;
if (XUL) {
element = (typeof XUL === "function" ? XUL : window.MozXULElement).parseXULToFragment(
xulString
);
element = (typeof XUL === "function" ? XUL : window.MozXULElement).parseXULToFragment(xulString);
} else {
element = new DOMParser().parseFromString(xulString, "text/html");
if (element.body.children.length) {
Expand All @@ -69,14 +72,14 @@ const appendXUL = (parentElement, xulString, insertBefore = null, XUL = false) =

const waitForElm = (selector) => {
return new Promise((resolve) => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const existing = document.querySelector(selector);
if (existing) return resolve(existing);

const observer = new MutationObserver(() => {
if (document.querySelector(selector)) {
const elm = document.querySelector(selector);
if (elm) {
observer.disconnect();
resolve(document.querySelector(selector));
resolve(elm);
}
});

Expand All @@ -87,28 +90,45 @@ const waitForElm = (selector) => {
});
};

const supportedLocales = ["en-US", "en", "pl"];
const supportedLocales = ["en-US", "en", "pl", "ru"];

const injectLocale = (file, doc = document) => {
const pref = "intl.locale.requested";
let link = null;

const getLocale = () => {
const appLocale = Services.locale.appLocaleAsLangTag;
return supportedLocales.includes(appLocale) ? appLocale : "en-US";
};

const register = () => {
let locale = Services.locale.appLocaleAsLangTag;
if (!supportedLocales.includes(locale)) {
locale = "en-US";
const locale = getLocale();

if (link) {
link.remove();
}
appendXUL(doc.head, `<link rel="localization" href="${locale}/${file}.ftl"/>`);
}

link = doc.createElement("link");
link.setAttribute("rel", "localization");
link.setAttribute("href", `${locale}/${file}.ftl`);
doc.head.appendChild(link);
};

register();

const pref = "intl.locale.requested";
const observer = {
observe() {
register();
}
},
};
Services.prefs.addObserver(pref, observer);
window.addEventListener("beforeunload", () => {
Services.prefs.removeObserver(pref, observer);
});
}
window.addEventListener(
"beforeunload",
() => {
Services.prefs.removeObserver(pref, observer);
},
{ once: true }
);
};

export default { parseMD, appendXUL, waitForElm, injectLocale };
5 changes: 5 additions & 0 deletions locales/ru/sine-cmdpalette.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
sine-cmd-placeholder =
.placeholder = Введите команду...

sine-cmd-refresh-mod-styles = Обновить стили модов
sine-cmd-open-mod-folder = Открыть папку с модами
86 changes: 86 additions & 0 deletions locales/ru/sine-preferences.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
pane-sine-mods-title = Моды Sine
category-sine-mods =
.tooltiptext = { pane-sine-mods-title }

pane-cosine-mods-title = Моды Cosine
category-cosine-mods =
.tooltiptext = { pane-cosine-mods-title }

sine-marketplace-header = Магазин

sine-mods-disable-all-enabled =
.title = Отключить все моды
sine-mods-disable-all-disabled =
.title = Включить все моды
sine-settings-button =
.title = Открыть настройки
sine-mods-marketplace-button =
.title = Перейти в магазин
sine-mods-search =
.placeholder = Поиск...
sine-refresh-marketplace =
.title = Обновить магазин
sine-marketplace-description = Ищите и устанавливайте моды из магазина
sine-install-description = или добавьте свой локально из GitHub-репозитория.
sine-install-input =
.placeholder = пользователь/репозиторий (и папка, если нужно)
sine-mod-install-label =
.label = Установить
sine-mod-install-title = Установить

sine-mods-installed-header = Установленные моды
sine-mods-auto-update-enabled =
.title = Отключить автообновление
sine-mods-auto-update-disabled =
.title = Включить автообновление
sine-mods-auto-update-title = Автообновление
sine-mods-manual-update-title = Проверить обновления
sine-mods-import-button =
.label = Импорт
sine-mods-export-button =
.label = Экспорт

sine-mods-update-checked = Обновлений нет
sine-mods-updated = Моды обновлены
sine-mod-indicator-updated =
.title = Этот мод был обновлён

sine-store-previous-button = Назад
sine-store-next-button = Вперёд

sine-settings-header = Настройки
sine-dialog-close = Закрыть

sine-mods-list-description = Список установленных модов Sine.
cosine-mods-list-description = Список установленных модов Cosine.

sine-mods-disabled-desc = Моды отключены. Включите их, чтобы управлять ими.
sine-no-mods-installed =
У вас нет установленных модов.
Посетите <a data-l10n-name="sine-marketplace-link">магазин</a>, чтобы установить моды.
sine-marketplace-link =
.href = https://sineorg.github.io/store/

sine-mod-disable-enabled =
.title = Отключить мод
sine-mod-disable-disabled =
.title = Включить мод
sine-mod-homepage-button =
.title = Перейти на домашнюю страницу
sine-mod-update-disable-enabled =
.title = Включить обновление для этого мода
sine-mod-update-disable-disabled =
.title = Отключить обновление для этого мода
sine-mod-remove-button = Удалить мод
sine-mod-remove-confirmation = Вы уверены, что хотите удалить этот мод?

sine-settings-general-title = **Основные**
sine-settings-external-marketplace = Разрешить сторонние магазины (может подвергнуть вас риску вредоносных JS-модов)
sine-settings-marketplace-url = URL магазина (прямая ссылка на GitHub или текст)
sine-settings-external-js = Разрешить установку JS из неофициальных источников (небезопасно, используйте на свой страх и риск)
sine-settings-dev-palette = Включить командную палитру разработчика. (Ctrl+Shift+Y)
sine-settings-update-title = **Обновления**
sine-settings-install-update = Установить обновление
sine-settings-restart = Перезапустить для применения изменений
sine-settings-update-branch = Ветка обновлений:
sine-settings-engine-auto-update = Включить автообновление движка
18 changes: 18 additions & 0 deletions locales/ru/sine-toasts.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
sine-toast-0 = Ошибка при копировании модов Zen.
sine-toast-1 = Мод, использующий JS, был удалён.
sine-toast-2 = Мод, использующий JS, был обновлён.
sine-toast-3 = Вы изменили настройку, для применения которой требуется перезапуск браузера.
sine-toast-4 = Не удалось прочитать настройки мода.
sine-toast-5 = Движок Sine был обновлён до версии v{ $version }.
sine-toast-6-enabled = Мод, использующий JS, был включён.
sine-toast-6-disabled = Мод, использующий JS, был отключён.

sine-toast-0-desc = Нажмите Ctrl+Shift+J для получения дополнительной информации.
sine-toast-1-desc = Для полной остановки его работы перезапустите браузер.
sine-toast-2-desc = Для его корректной работы перезапустите браузер.
sine-toast-4-desc = Пожалуйста, удалите и переустановите { $name }.
sine-toast-5-desc = Пожалуйста, перезапустите браузер, чтобы изменения полностью вступили в силу.
sine-toast-6-desc = Для полного восстановления его работы перезапустите браузер.

sine-toast-preset-1 = Перезапустить
sine-toast-preset-2 = Включить
61 changes: 0 additions & 61 deletions scripts/update.py

This file was deleted.