mirror of
https://github.com/vrc-get/vrc-get.git
synced 2026-06-21 09:58:08 +00:00
chore: change how do we pass customized message
This commit is contained in:
parent
6fb9f631a1
commit
4e31d23b0c
7 changed files with 82 additions and 76 deletions
|
|
@ -84,21 +84,6 @@ nix = { version = "0.31", features = ["fs"] }
|
|||
# DO NOT REMOVE!!
|
||||
custom-protocol = [ "tauri/custom-protocol" ]
|
||||
|
||||
# Feature flags for ALCOM.
|
||||
# Some flags are negative flag that is not recommended by cargo,
|
||||
# but our app is not library so OK for now.
|
||||
|
||||
# Disable updater
|
||||
# This feature flag disables the built-in updater feature.
|
||||
# Useful when ALCOM is managed by a package manager.
|
||||
#
|
||||
# It is recommended to set the following build-time environment variables:
|
||||
# ALCOM_UPDATE_UPDATER_DISABLED_MESSAGE
|
||||
# ALCOM_UPDATE_UPDATER_DISABLED_${LOCALE}_MESSAGE
|
||||
# where ${LOCALE} is the language name in uppercase.
|
||||
#
|
||||
# These variables should instruct users how to update ALCOM
|
||||
# using the package manager provided by the distribution.
|
||||
no-self-updater = []
|
||||
|
||||
# Devtools
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { commands } from "@/lib/bindings";
|
|||
import { callAsyncCommand } from "@/lib/call-async-command";
|
||||
import type { DialogContext } from "@/lib/dialog";
|
||||
import globalInfo from "@/lib/global-info";
|
||||
import { tc } from "@/lib/i18n";
|
||||
import { localizeExternalComponent, tc } from "@/lib/i18n";
|
||||
|
||||
type ConfirmStatus =
|
||||
| {
|
||||
|
|
@ -128,10 +128,10 @@ export function CheckForUpdateMessage({
|
|||
"check update:dialog:new version updater disabled base description",
|
||||
)}
|
||||
<br />
|
||||
{tc([
|
||||
"from-env:updater disabled message",
|
||||
"check update:dialog:new version updater how to upgrade fallback",
|
||||
])}
|
||||
{localizeExternalComponent(response.updater_disabled_messages, {
|
||||
localized:
|
||||
"check update:dialog:new version updater how to upgrade fallback",
|
||||
})}
|
||||
</p>
|
||||
);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ async deepLinkReduceImportedClearNonToastedCount(reduce: number) : Promise<void>
|
|||
|
||||
export type AddRepositoryInfo = { url: string; headers: { [key in string]: string } }
|
||||
export type AsyncCallResult<P, R> = { type: "Result"; value: R } | { type: "Started" } | { type: "UnusedProgress"; progress: P }
|
||||
export type CheckForUpdateResponse = { version: number; current_version: string; latest_version: string; updater_status: UpdaterStatus; update_description: string | null }
|
||||
export type CheckForUpdateResponse = { version: number; current_version: string; latest_version: string; updater_status: UpdaterStatus; update_description: string | null; updater_disabled_messages: { [key in string]: string } | null }
|
||||
/**
|
||||
* Errors that is expected to be handled on the GUI side
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -22,26 +22,6 @@ const languageResources = {
|
|||
zh_hant: zh_hantJson,
|
||||
};
|
||||
|
||||
// merge messages from environment
|
||||
function mergeMessage(
|
||||
envMessages: Record<string, string> | null,
|
||||
key: string,
|
||||
languageResources: Record<string, Record<string, Record<string, unknown>>>,
|
||||
) {
|
||||
if (envMessages == null) return;
|
||||
for (const [locale, message] of Object.entries(envMessages)) {
|
||||
const localeMessages = languageResources[locale]?.translation;
|
||||
if (localeMessages) {
|
||||
localeMessages[key] = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
mergeMessage(
|
||||
ALCOM_UPDATE_UPDATER_DISABLED_MESSAGE,
|
||||
"from-env:updater disabled message",
|
||||
languageResources as never,
|
||||
);
|
||||
|
||||
i18next.use(initReactI18next).init({
|
||||
resources: languageResources as Resource,
|
||||
lng: "en",
|
||||
|
|
@ -88,3 +68,72 @@ export function tc(
|
|||
}
|
||||
|
||||
export const tt = i18nextt;
|
||||
|
||||
// Helper component, type, and function for externally provided localization
|
||||
|
||||
// Key is name of locale, value is message in its locale.
|
||||
type ExternalLocalization = Record<string, string> | null;
|
||||
type Fallback = { plain: string } | { localized: string };
|
||||
|
||||
function localizeExternalImpl(
|
||||
i18n: typeof i18next,
|
||||
localization: ExternalLocalization,
|
||||
): string | undefined {
|
||||
if (localization == null) return undefined;
|
||||
for (const language of i18n.languages) {
|
||||
// biome-ignore lint/suspicious/noPrototypeBuiltins: we're targeting 2021
|
||||
if (Object.prototype.hasOwnProperty.call(i18n, language)) {
|
||||
const localized = localization[language];
|
||||
if (localized) {
|
||||
return localized;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function localizeExternal(
|
||||
localization: ExternalLocalization,
|
||||
fallback: Fallback,
|
||||
) {
|
||||
const localized = localizeExternalImpl(i18next, localization);
|
||||
if (localized) {
|
||||
return localized;
|
||||
}
|
||||
if ("plain" in fallback) {
|
||||
return fallback.plain;
|
||||
}
|
||||
return i18next.t(fallback.localized);
|
||||
}
|
||||
|
||||
function LocalizeExternalComponentImpl({
|
||||
localization,
|
||||
fallback,
|
||||
}: {
|
||||
localization: ExternalLocalization;
|
||||
fallback: Fallback;
|
||||
}) {
|
||||
const { i18n } = useTranslation();
|
||||
|
||||
const localized = localizeExternalImpl(i18n, localization);
|
||||
if (localized) {
|
||||
return React.createElement(Trans, {
|
||||
defaults: localized,
|
||||
components: { ExternalLink: React.createElement(ExternalLink) },
|
||||
});
|
||||
}
|
||||
if ("plain" in fallback) {
|
||||
return fallback.plain;
|
||||
}
|
||||
return i18n.t(fallback.localized);
|
||||
}
|
||||
|
||||
export function localizeExternalComponent(
|
||||
localization: ExternalLocalization,
|
||||
fallback: Fallback,
|
||||
) {
|
||||
return React.createElement(LocalizeExternalComponentImpl, {
|
||||
localization,
|
||||
fallback,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ pub struct CheckForUpdateResponse {
|
|||
latest_version: String,
|
||||
updater_status: updater::UpdaterStatus,
|
||||
update_description: Option<String>,
|
||||
updater_disabled_messages: Option<indexmap::IndexMap<String, String>>,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
|
|
@ -97,6 +98,11 @@ pub async fn util_check_for_update(
|
|||
let latest_version = response.version.clone();
|
||||
let updater_status = response.updater_status;
|
||||
let update_description = response.body.clone();
|
||||
let updater_disabled_messages = if cfg!(feature = "no-self-updater") {
|
||||
option_env!("ALCOM_UPDATER_DISABLED_MESSAGE").and_then(|x| serde_json::from_str(x).ok())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let version = updater_state.set(response);
|
||||
Ok(Some(CheckForUpdateResponse {
|
||||
|
|
@ -105,6 +111,7 @@ pub async fn util_check_for_update(
|
|||
latest_version,
|
||||
updater_status,
|
||||
update_description,
|
||||
updater_disabled_messages,
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
|||
4
vrc-get-gui/vite-env.d.ts
vendored
4
vrc-get-gui/vite-env.d.ts
vendored
|
|
@ -1,5 +1 @@
|
|||
/// <reference types="vite/client" />
|
||||
declare const ALCOM_UPDATE_UPDATER_DISABLED_MESSAGE: Record<
|
||||
string,
|
||||
string
|
||||
> | null;
|
||||
|
|
|
|||
|
|
@ -43,35 +43,4 @@ export default defineConfig({
|
|||
},
|
||||
},
|
||||
clearScreen: false,
|
||||
define: {
|
||||
ALCOM_UPDATE_UPDATER_DISABLED_MESSAGE: JSON.stringify(
|
||||
makeEnvMessageTable("ALCOM_UPDATE_UPDATER_DISABLED"),
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
function makeEnvMessageTable(envName: string): Record<string, string> | null {
|
||||
const env = process.env;
|
||||
const english = env[`${envName}_MESSAGE`];
|
||||
// first check for en message
|
||||
if (!english) return null;
|
||||
|
||||
// there is english message. We'll add other languages as well
|
||||
const result: Record<string, string> = {};
|
||||
|
||||
const regex = new RegExp(`^${envName}_(?<locale>[A-Z_]+)_MESSAGE$`);
|
||||
|
||||
for (const [envName, envValue] of Object.entries(process.env)) {
|
||||
if (!envValue) continue;
|
||||
const matchResult = regex.exec(envValue);
|
||||
if (matchResult == null) continue;
|
||||
// biome-ignore lint/style/noNonNullAssertion: we have defined match group.
|
||||
const localeName = matchResult.groups!.locale.toLowerCase();
|
||||
if (localeName.length === 0) continue;
|
||||
result[localeName] = envValue;
|
||||
}
|
||||
|
||||
result.en = english;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue