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
8 changes: 5 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/folio/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
},
"devDependencies": {
"@google-labs/tsconfig": "^0.0.2",
"@lit/localize-tools": "^0.8.1",
"@lit/localize-tools": "^0.8.2",
"vite": "^7.3.2",
"wireit": "^0.15.0-pre.2"
},
Expand Down
10 changes: 10 additions & 0 deletions packages/visual-editor/localization/de.xlb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<localizationbundle locale="de">
<messages>
<msg name="hbeb436a6f6a2a826">Dieses Gem wird von Google Labs bereitgestellt, nicht von Gemini Apps. Es kann
Fehler machen. Bitte überprüfen Sie die Ergebnisse.
<ph name="0">&lt;a href="https://support.google.com/gemini?p=ai_apps"&gt;</ph>Weitere Informationen<ph name="1">&lt;/a&gt;</ph></msg>
<msg name="s718207f6b5b1ed0b">Ich möchte E-Mails zu Modellaktualisierungen, Angeboten, nützlichen Tipps und Neuigkeiten zu Opal erhalten</msg>
<msg name="s018656f690df2a0e">Ich möchte zu künftigen Nutzerstudien von Opal eingeladen werden</msg>
</messages>
</localizationbundle>
10 changes: 10 additions & 0 deletions packages/visual-editor/localization/fr.xlb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<localizationbundle locale="fr">
<messages>
<msg name="hbeb436a6f6a2a826">Ce Gem est fourni par Google Labs, et non par Gemini Apps. Il peut
faire des erreurs, veuillez donc vérifier les résultats.
<ph name="0">&lt;a href="https://support.google.com/gemini?p=ai_apps"&gt;</ph>En savoir plus<ph name="1">&lt;/a&gt;</ph></msg>
<msg name="s718207f6b5b1ed0b">Je souhaite recevoir des e-mails concernant les mises à jour des modèles, les offres, les conseils utiles et les actualités d'Opal</msg>
<msg name="s018656f690df2a0e">Je souhaite être invité(e) à participer à de futures études de recherche d'Opal</msg>
</messages>
</localizationbundle>
17 changes: 17 additions & 0 deletions packages/visual-editor/localization/lit-localize.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "https://raw.githubusercontent.com/lit/lit/main/packages/localize-tools/config.schema.json",
"sourceLocale": "en",
"targetLocales": ["fr", "de"],
"tsConfig": "../tsconfig.json",
"output": {
"mode": "runtime",
"outputDir": "../src/generated/localization",
"language": "ts",
"localeCodesModule": "src/generated/localization/locale-codes.ts"
},
"interchange": {
"format": "xlb",
"outputFile": "messages.xmb",
"translationsGlob": "*.xlb"
}
}
10 changes: 10 additions & 0 deletions packages/visual-editor/localization/messages.xmb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<localizationbundle locale="en">
<messages>
<msg name="hbeb436a6f6a2a826">This Gem is powered by Google Labs, not Gemini Apps. It can
make mistakes, so double-check it.
<ph name="0">&lt;a href="https://support.google.com/gemini?p=ai_apps"&gt;</ph>Learn more<ph name="1">&lt;/a&gt;</ph></msg>
<msg name="s718207f6b5b1ed0b">I’d like to receive emails for model updates, offers, useful tips and news about Opal</msg>
<msg name="s018656f690df2a0e">I’m interested in being invited to future research studies from Opal</msg>
</messages>
</localizationbundle>
29 changes: 28 additions & 1 deletion packages/visual-editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
"lint": "wireit",
"export-functions": "wireit",
"import-declarations": "wireit",
"build:opie-instructions": "wireit"
"build:opie-instructions": "wireit",
"localize:extract": "wireit",
"localize:build": "wireit"
},
"wireit": {
"build": {
Expand Down Expand Up @@ -269,6 +271,29 @@
"output": [
"src/a2/agent/graph-editing/instructions/generated.ts"
]
},
"localize:extract": {
"command": "lit-localize extract --config localization/lit-localize.json",
"files": [
"src/**/*.ts",
"!src/generated/localization/",
"localization/lit-localize.json"
],
"output": [
"localization/messages.xmb"
]
},
"localize:build": {
"command": "lit-localize build --config localization/lit-localize.json",
"files": [
"src/**/*.ts",
"!src/generated/localization/",
"localization/*.xlb",
"localization/lit-localize.json"
],
"output": [
"src/generated/localization/"
]
}
},
"repository": {
Expand All @@ -291,6 +316,8 @@
"devDependencies": {
"@cfworker/json-schema": "^4.1.1",
"@google-labs/tsconfig": "^0.0.2",
"@lit/localize": "^0.12.2",
"@lit/localize-tools": "^0.8.2",
"@tweakpane/core": "^2.0.5",
"@types/flubber": "^0.4.0",
"@types/gapi": "^0.0.47",
Expand Down
4 changes: 4 additions & 0 deletions packages/visual-editor/src/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { makeUrl, OAUTH_REDIRECT, parseUrl } from "./ui/navigation/urls.js";
import { CLIENT_DEPLOYMENT_CONFIG } from "./ui/config/client-deployment-configuration.js";
import { connectToOpalShellHost } from "./ui/utils/opal-shell-guest.js";
import { Utils } from "./sca/utils.js";
import { setLocale } from "./localization/config.js";

export { bootstrap };

Expand Down Expand Up @@ -68,6 +69,9 @@ async function bootstrap(bootstrapArgs: BootstrapArguments) {

const guestConfiguration = await shellHost.getConfiguration();
const parsedUrl = parseUrl(window.location.href);
if (parsedUrl.hl) {
await setLocale(parsedUrl.hl);
}
const { lite, page, colorScheme } = parsedUrl;
if (
// Signed-out users can access public graphs.
Expand Down
18 changes: 18 additions & 0 deletions packages/visual-editor/src/generated/localization/de.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

// Do not modify this file by hand!
// Re-generate this file by running lit-localize

import {html} from 'lit';


/* eslint-disable no-irregular-whitespace */
/* eslint-disable @typescript-eslint/no-explicit-any */

export const templates = {
'hbeb436a6f6a2a826': html`Dieses Gem wird von Google Labs bereitgestellt, nicht von Gemini Apps. Es kann
Fehler machen. Bitte überprüfen Sie die Ergebnisse.
<a href="https://support.google.com/gemini?p=ai_apps">Weitere Informationen</a>`,
's018656f690df2a0e': `Ich möchte zu künftigen Nutzerstudien von Opal eingeladen werden`,
's718207f6b5b1ed0b': `Ich möchte E-Mails zu Modellaktualisierungen, Angeboten, nützlichen Tipps und Neuigkeiten zu Opal erhalten`,
};

18 changes: 18 additions & 0 deletions packages/visual-editor/src/generated/localization/fr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

// Do not modify this file by hand!
// Re-generate this file by running lit-localize

import {html} from 'lit';


/* eslint-disable no-irregular-whitespace */
/* eslint-disable @typescript-eslint/no-explicit-any */

export const templates = {
'hbeb436a6f6a2a826': html`Ce Gem est fourni par Google Labs, et non par Gemini Apps. Il peut
faire des erreurs, veuillez donc vérifier les résultats.
<a href="https://support.google.com/gemini?p=ai_apps">En savoir plus</a>`,
's018656f690df2a0e': `Je souhaite être invité(e) à participer à de futures études de recherche d'Opal`,
's718207f6b5b1ed0b': `Je souhaite recevoir des e-mails concernant les mises à jour des modèles, les offres, les conseils utiles et les actualités d'Opal`,
};

25 changes: 25 additions & 0 deletions packages/visual-editor/src/generated/localization/locale-codes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Do not modify this file by hand!
// Re-generate this file by running lit-localize.

/**
* The locale code that templates in this source code are written in.
*/
export const sourceLocale = `en`;

/**
* The other locale codes that this application is localized into. Sorted
* lexicographically.
*/
export const targetLocales = [
`de`,
`fr`,
] as const;

/**
* All valid project locale codes. Sorted lexicographically.
*/
export const allLocales = [
`de`,
`en`,
`fr`,
] as const;
6 changes: 4 additions & 2 deletions packages/visual-editor/src/index-lite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { blankBoard } from "./ui/utils/blank-board.js";
import { repeat } from "lit/directives/repeat.js";
import { createRef, ref, Ref } from "lit/directives/ref.js";

import { markdown } from "./ui/directives/markdown.js";
import { msg } from "@lit/localize";
import { type SharePanel } from "./ui/elements/elements.js";
import { deriveLiteViewType } from "./sca/utils/lite-view-type.js";
import {
Expand Down Expand Up @@ -665,7 +665,9 @@ export class LiteMain extends MainBase implements LiteEditInputController {

#renderMessage() {
return html`<div id="message" class="w-400 md-body-small sans-flex">
${markdown(Strings.from("LABEL_DISCLAIMER_LITE"))}
${msg(html`This Gem is powered by Google Labs, not Gemini Apps. It can
make mistakes, so double-check it.
<a href="https://support.google.com/gemini?p=ai_apps">Learn more</a>`)}
</div>`;
}

Expand Down
28 changes: 28 additions & 0 deletions packages/visual-editor/src/localization/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import { configureLocalization, type LocaleModule } from "@lit/localize";
import {
sourceLocale,
targetLocales,
} from "../generated/localization/locale-codes.js";

// Non-standard Vite function. Detects all available locales at build time and
// substitutes static module names for the dynamic imports.
const localeModules = import.meta.glob("../generated/localization/*.ts");

const { setLocale } = configureLocalization({
sourceLocale,
targetLocales,
loadLocale: (locale) => {
const loader = localeModules[`../generated/localization/${locale}.ts`];
if (!loader) {
return Promise.reject(new Error(`Unknown locale: ${locale}`));
}
return loader() as Promise<LocaleModule>;
},
});
export { setLocale };
4 changes: 1 addition & 3 deletions packages/visual-editor/src/opal-lang.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ export default {
LABEL_DISCLAIMER: {
str: "Opal can make mistakes, so double-check it",
},
LABEL_DISCLAIMER_LITE: {
str: "This Gem is powered by Google Labs, not Gemini Apps. It can make mistakes, so double-check it. [Learn more](https://support.google.com/gemini?p=ai_apps)",
},

LABEL_FIRST_RUN: {
str: "Click start to try this Opal",
},
Expand Down
1 change: 1 addition & 0 deletions packages/visual-editor/src/sca/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export interface BaseUrlInit {
forceSurveySelection?: "true";
};
oauthRedirect?: string;
hl?: string;
lite?: boolean;
colorScheme?: "light" | "dark";
guestPrefixed: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import { LitElement, html, css, nothing } from "lit";
import { msg } from "@lit/localize";
import { customElement, property, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { baseColors } from "../../styles/host/base-colors.js";
Expand Down Expand Up @@ -189,7 +190,7 @@ export class VEGlobalSettingsModal extends SignalWatcher(LitElement) {
["OPAL_MARKETING_UPDATES", target.checked],
])}
></md-checkbox>
${Strings.from("LABEL_EMAIL_UPDATES")}
${msg("I’d like to receive emails for model updates, offers, useful tips and news about Opal")}
</label>
<label
class=${classMap({
Expand All @@ -206,7 +207,7 @@ export class VEGlobalSettingsModal extends SignalWatcher(LitElement) {
["OPAL_USER_RESEARCH", target.checked],
])}
></md-checkbox>
${Strings.from("LABEL_EMAIL_RESEARCH")}
${msg("I’m interested in being invited to future research studies from Opal")}
</label>`,
},
[TabId.INTEGRATIONS]: {
Expand Down
5 changes: 3 additions & 2 deletions packages/visual-editor/src/ui/elements/shell/warm-welcome.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import { LitElement, html, css } from "lit";
import { msg } from "@lit/localize";
import { customElement, state, property } from "lit/decorators.js";
import { baseColors } from "../../styles/host/base-colors.js";
import { type } from "../../styles/host/type.js";
Expand Down Expand Up @@ -96,15 +97,15 @@ export class VEWarmWelcomeModal extends LitElement {
@change=${({ target }: { target: MdCheckbox }) =>
(this.emailUpdates = target.checked)}
></md-checkbox>
${Strings.from("LABEL_EMAIL_UPDATES")}
${msg("I’d like to receive emails for model updates, offers, useful tips and news about Opal")}
</label>
<label class="md-body-large">
<md-checkbox
.checked=${this.userResearch}
@change=${({ target }: { target: MdCheckbox }) =>
(this.userResearch = target.checked)}
></md-checkbox>
${Strings.from("LABEL_EMAIL_RESEARCH")}
${msg("I’m interested in being invited to future research studies from Opal")}
</label>
</bb-modal> `;
}
Expand Down
14 changes: 14 additions & 0 deletions packages/visual-editor/src/ui/navigation/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const MISSING_SCOPES = "missing-scopes";
const AUTO_SIGN_IN = "auto-sign-in";
const RESOURCE_KEY = "resourcekey";
export const OAUTH_REDIRECT = "oauth_redirect";
const HL = "hl";
const DEV_PREFIX = "dev-";

/**
Expand Down Expand Up @@ -173,6 +174,9 @@ export function makeUrl(
`unhandled page ${JSON.stringify(page)} from ${JSON.stringify(init)}`
);
}
if (init.hl) {
url.searchParams.set(HL, init.hl);
}
if (init.dev) {
for (const [key, val] of Object.entries(
init.dev as Record<string, string>
Expand Down Expand Up @@ -200,6 +204,7 @@ export function parseUrl(url: string | URL): MakeUrlInit {
}
let dev: BaseUrlInit["dev"];
const oauthRedirect = url.searchParams.get(OAUTH_REDIRECT);
const hl = url.searchParams.get(HL);
for (const [key, val] of url.searchParams) {
if (key.startsWith(DEV_PREFIX)) {
dev ??= {};
Expand Down Expand Up @@ -250,6 +255,9 @@ export function parseUrl(url: string | URL): MakeUrlInit {
if (dev) {
landing.dev = dev;
}
if (hl) {
landing.hl = hl;
}
return landing;
} else if (pathname.startsWith("/open/")) {
const open: OpenUrlInit = {
Expand Down Expand Up @@ -291,6 +299,9 @@ export function parseUrl(url: string | URL): MakeUrlInit {
if (oauthRedirect) {
home.oauthRedirect = oauthRedirect;
}
if (hl) {
home.hl = hl;
}
return home;
}
const mode =
Expand Down Expand Up @@ -325,6 +336,9 @@ export function parseUrl(url: string | URL): MakeUrlInit {
if (oauthRedirect) {
graph.oauthRedirect = oauthRedirect;
}
if (hl) {
graph.hl = hl;
}
return graph;
}
}
Loading
Loading