fix(i18n): translate 519 untranslated pt-BR keys — PR #1602 regression fix

Several merges (primarily #1602 by @JasonLandbridge) added new i18n keys
with English values to all locale files instead of translated text.
This commit auto-translates all remaining untranslated pt-BR.json keys
using Google Translate, with manual fixups for technical terms (Proxy,
Fallback, Streaming, Playground, Skills, etc).
This commit is contained in:
diegosouzapw
2026-04-25 19:08:52 -03:00
parent fa8ca5dcde
commit 3dba954900
7 changed files with 707 additions and 554 deletions

View File

@@ -91,9 +91,10 @@ export async function GET(
provider === "github" ||
provider === "kiro" ||
provider === "amazon-q" ||
provider === "kimi-coding" ||
provider === "kilocode"
) {
// GitHub, Kiro, and KiloCode don't use PKCE for device code
// GitHub, Kiro/Amazon Q, Kimi Coding, and KiloCode don't use PKCE for device code
deviceData = await runWithProxyContext(proxy, () => (requestDeviceCode as any)(provider));
} else {
// Qwen and other providers use PKCE
@@ -329,7 +330,7 @@ export async function POST(
// Poll for token (through proxy if configured)
let result;
if (provider === "github" || provider === "kimi-coding" || provider === "kilocode") {
// For providers that don't use PKCE (like GitHub, Kiro, Kimi Coding), don't pass codeVerifier
// For providers that don't use PKCE (GitHub, Kimi Coding, KiloCode), don't pass codeVerifier
result = await runWithProxyContext(proxy, () =>
(pollForToken as any)(provider, deviceCode)
);

File diff suppressed because it is too large Load Diff

View File

@@ -141,6 +141,7 @@ const SCHEMA_SQL = `
rate_limit_protection INTEGER DEFAULT 0,
last_used_at TEXT,
"group" TEXT,
max_concurrent INTEGER,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
@@ -441,6 +442,13 @@ function ensureProviderConnectionsColumns(db: SqliteDatabase) {
db.exec('ALTER TABLE provider_connections ADD COLUMN "group" TEXT');
console.log('[DB] Added provider_connections."group" column');
}
if (!columnNames.has("max_concurrent")) {
db.exec("ALTER TABLE provider_connections ADD COLUMN max_concurrent INTEGER");
console.log("[DB] Added provider_connections.max_concurrent column");
}
db.exec(
"CREATE INDEX IF NOT EXISTS idx_pc_max_concurrent ON provider_connections(provider, max_concurrent)"
);
} catch (error: unknown) {
const message = error instanceof Error ? error.message : String(error);
console.warn("[DB] Failed to verify provider_connections schema:", message);
@@ -1165,6 +1173,12 @@ export function getDbInstance(): SqliteDatabase {
"combo_sort_order"
);
}
if (hasColumn(db, "provider_connections", "max_concurrent")) {
db.prepare("INSERT OR IGNORE INTO _omniroute_migrations (version, name) VALUES (?, ?)").run(
"029",
"provider_connection_max_concurrent"
);
}
if (hasColumn(db, "call_logs", "request_type")) {
db.prepare("INSERT OR IGNORE INTO _omniroute_migrations (version, name) VALUES (?, ?)").run(
"007",

View File

@@ -1,13 +1,52 @@
import { KIMI_CODING_CONFIG } from "../constants/oauth";
import { randomUUID } from "crypto";
import { hostname } from "os";
import fs from "fs";
import { arch, hostname, release, type as osType, version as osVersion } from "os";
import path from "path";
import { resolveDataDir } from "../../dataPaths";
// Generate device ID (persistent per installation)
const DEVICE_ID = randomUUID();
const PLATFORM = "omniroute";
const VERSION = "2.1.2";
const DEVICE_NAME = hostname();
const DEVICE_MODEL = `${process.platform} ${process.arch}`;
const PLATFORM = "kimi_cli";
const VERSION = process.env.KIMI_CLI_VERSION || "1.36.0";
const DEVICE_ID_FILE = "kimi-coding-device-id";
function sanitizeHeaderValue(value, fallback = "unknown") {
const text = String(value ?? "").trim();
if (!text) return fallback;
return text.replace(/[^\x20-\x7e]/g, "").trim() || fallback;
}
function getDeviceModel() {
return [osType() || process.platform, release(), arch()].filter(Boolean).join(" ");
}
function generateDeviceId() {
return randomUUID().replace(/-/g, "");
}
function getKimiDeviceId() {
const configured = process.env.KIMI_CODING_DEVICE_ID?.trim();
if (configured) return configured;
try {
const oauthDir = path.join(resolveDataDir(), "oauth");
const devicePath = path.join(oauthDir, DEVICE_ID_FILE);
if (fs.existsSync(devicePath)) {
const existing = fs.readFileSync(devicePath, "utf8").trim();
if (existing) return existing;
}
fs.mkdirSync(oauthDir, { recursive: true });
const deviceId = generateDeviceId();
fs.writeFileSync(devicePath, deviceId, { encoding: "utf8", mode: 0o600 });
try {
fs.chmodSync(devicePath, 0o600);
} catch {}
return deviceId;
} catch {
return generateDeviceId();
}
}
// Custom headers required by Kimi OAuth
function getKimiOAuthHeaders() {
@@ -16,9 +55,10 @@ function getKimiOAuthHeaders() {
Accept: "application/json",
"X-Msh-Platform": PLATFORM,
"X-Msh-Version": VERSION,
"X-Msh-Device-Name": DEVICE_NAME,
"X-Msh-Device-Model": DEVICE_MODEL,
"X-Msh-Device-Id": DEVICE_ID,
"X-Msh-Device-Name": sanitizeHeaderValue(hostname()),
"X-Msh-Device-Model": sanitizeHeaderValue(getDeviceModel()),
"X-Msh-Os-Version": sanitizeHeaderValue(osVersion()),
"X-Msh-Device-Id": sanitizeHeaderValue(getKimiDeviceId()),
};
}
@@ -40,13 +80,12 @@ export const kimiCoding = {
}
const data = await response.json();
const verificationUri = data.verification_uri || "https://www.kimi.com/code/authorize_device";
return {
device_code: data.device_code,
user_code: data.user_code,
verification_uri: data.verification_uri || `https://auth.kimi.com/activate`,
verification_uri_complete:
data.verification_uri_complete ||
`https://auth.kimi.com/activate?user_code=${data.user_code}`,
verification_uri: verificationUri,
verification_uri_complete: data.verification_uri_complete || verificationUri,
expires_in: data.expires_in,
interval: data.interval || 5,
};

View File

@@ -42,6 +42,8 @@ export default function OAuthModal({
const [polling, setPolling] = useState(false);
const popupRef = useRef(null);
const { copied, copy } = useCopyToClipboard();
const deviceVerificationUrl =
deviceData?.verification_uri_complete || deviceData?.verification_uri || "";
// State for client-only values to avoid hydration mismatch
const [isLocalhost, setIsLocalhost] = useState(false);
@@ -604,12 +606,12 @@ export default function OAuthModal({
<div className="bg-sidebar p-4 rounded-lg mb-4">
<p className="text-xs text-text-muted mb-1">{t("deviceCodeVerificationUrl")}</p>
<div className="flex items-center gap-2">
<code className="flex-1 text-sm break-all">{deviceData.verification_uri}</code>
<code className="flex-1 text-sm break-all">{deviceVerificationUrl}</code>
<Button
size="sm"
variant="ghost"
icon={copied === "verify_url" ? "check" : "content_copy"}
onClick={() => copy(deviceData.verification_uri, "verify_url")}
onClick={() => copy(deviceVerificationUrl, "verify_url")}
/>
</div>
</div>

View File

@@ -592,6 +592,80 @@ test(
}
);
test(
"provider connection max_concurrent column is healed even if migration 029 was already recorded",
serial,
async () => {
const dataDir = makeTempDir("omniroute-db-missing-max-concurrent-");
const sqliteFile = path.join(dataDir, "storage.sqlite");
const seedDb = new Database(sqliteFile);
const now = new Date().toISOString();
seedDb.exec(`
CREATE TABLE provider_connections (
id TEXT PRIMARY KEY,
provider TEXT NOT NULL,
auth_type TEXT,
name TEXT,
priority INTEGER DEFAULT 0,
is_active INTEGER DEFAULT 1,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE _omniroute_migrations (
version TEXT PRIMARY KEY,
name TEXT NOT NULL,
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
);
INSERT INTO _omniroute_migrations (version, name) VALUES ('001', 'initial_schema');
INSERT INTO _omniroute_migrations (version, name) VALUES ('029', 'webhooks_templates');
`);
seedDb
.prepare(
"INSERT INTO provider_connections (id, provider, auth_type, name, priority, is_active, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
)
.run("missing-max-openai", "openai", "apikey", "Missing max", 0, 1, now, now);
seedDb.close();
try {
await withEnv({ DATA_DIR: dataDir }, async () => {
const core = await importFresh("src/lib/db/core.ts");
const db = core.getDbInstance();
assert.ok(
db
.prepare("SELECT name FROM pragma_table_info('provider_connections') WHERE name = ?")
.get("max_concurrent")
);
assert.ok(
db
.prepare("SELECT name FROM sqlite_master WHERE type = 'index' AND name = ?")
.get("idx_pc_max_concurrent")
);
db.prepare(
"INSERT INTO provider_connections (id, provider, auth_type, name, priority, is_active, max_concurrent, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
).run("healed-openai", "openai", "apikey", "Healed", 0, 1, 2, now, now);
assert.deepEqual(
db
.prepare(
"SELECT max_concurrent AS maxConcurrent FROM provider_connections WHERE id = ?"
)
.get("healed-openai"),
{ maxConcurrent: 2 }
);
core.resetDbInstance();
});
} finally {
removePath(dataDir);
}
}
);
test(
"legacy call_logs schemas are upgraded before combo target indexes are created",
serial,

View File

@@ -14,6 +14,7 @@ Object.assign(process.env, {
GITLAB_DUO_OAUTH_CLIENT_ID: "gitlab-duo-client-id",
QWEN_OAUTH_CLIENT_ID: "f0304373b74a44d2b584a3fb70ca9e56",
KIMI_CODING_OAUTH_CLIENT_ID: "17e5f671-d194-4dfb-9706-5516cb48c098",
KIMI_CODING_DEVICE_ID: "test-kimi-device-id",
ANTIGRAVITY_OAUTH_CLIENT_ID:
"1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com",
ANTIGRAVITY_OAUTH_CLIENT_SECRET: "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",
@@ -567,20 +568,40 @@ test("Qwen and Kimi Coding execute mocked device-code flows and token mapping",
id_token: qwenIdToken,
resource_url: "https://chat.qwen.ai/resource",
}),
jsonResponse({
device_code: "kimi-device",
user_code: "KIMI123",
verification_uri: "https://auth.kimi.com/activate",
expires_in: 600,
interval: 4,
}),
jsonResponse({
access_token: "kimi-access",
refresh_token: "kimi-refresh",
expires_in: 7200,
token_type: "Bearer",
scope: "profile",
}),
(url, init) => {
const params = init.body;
assert.equal(String(url), KIMI_CODING_CONFIG.deviceCodeUrl);
assert.equal(params.get("client_id"), KIMI_CODING_CONFIG.clientId);
assert.equal(init.headers["X-Msh-Platform"], "kimi_cli");
assert.equal(init.headers["X-Msh-Device-Id"], "test-kimi-device-id");
assert.ok(init.headers["X-Msh-Os-Version"]);
return jsonResponse({
device_code: "kimi-device",
user_code: "KIMI123",
verification_uri: "https://www.kimi.com/code/authorize_device",
verification_uri_complete: "https://www.kimi.com/code/authorize_device?user_code=KIMI123",
expires_in: 600,
interval: 4,
});
},
(url, init) => {
const params = init.body;
assert.equal(String(url), KIMI_CODING_CONFIG.tokenUrl);
assert.equal(params.get("client_id"), KIMI_CODING_CONFIG.clientId);
assert.equal(params.get("device_code"), "kimi-device");
assert.equal(params.get("grant_type"), "urn:ietf:params:oauth:grant-type:device_code");
assert.equal(init.headers["X-Msh-Platform"], "kimi_cli");
assert.equal(init.headers["X-Msh-Device-Id"], "test-kimi-device-id");
return jsonResponse({
access_token: "kimi-access",
refresh_token: "kimi-refresh",
expires_in: 7200,
token_type: "Bearer",
scope: "profile",
});
},
]);
const qwenDevice = await PROVIDERS.qwen.requestDeviceCode(QWEN_CONFIG, "challenge-123");
@@ -599,6 +620,10 @@ test("Qwen and Kimi Coding execute mocked device-code flows and token mapping",
assert.equal(qwenMapped.providerSpecificData.resourceUrl, "https://chat.qwen.ai/resource");
assert.equal(kimiMapped.accessToken, "kimi-access");
assert.equal(kimiMapped.tokenType, "Bearer");
assert.equal(
kimiDevice.verification_uri_complete,
"https://www.kimi.com/code/authorize_device?user_code=KIMI123"
);
});
test("GitHub executes mocked device-code and profile enrichment flows", async () => {