Skip to content

Commit cb14614

Browse files
committed
Add Traditional Chinese localization files for TimeLens
- Created browserUsage.json for browser usage tracking interface. - Added categories.json for application categorization features. - Introduced common.json for shared UI elements and messages. - Implemented dashboard.json for the main dashboard interface. - Developed focus.json for focus mode functionalities. - Added goals.json for setting usage goals for applications and categories. - Created limits.json for daily usage limits and notifications. - Introduced settings.json for application configuration options. - Added widgets.json for managing and customizing widgets.
1 parent 3fb2651 commit cb14614

52 files changed

Lines changed: 975 additions & 58 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"extensionName": {
3+
"message": "TimeLens 瀏覽器夥伴翸"
4+
},
5+
"extensionDescription": {
6+
"message": "TimeLens 瀏覽器夥伴。追蹤活躍分頁工作階段,偵測閒置狀態,並將瀏覽器使用資料同步到本機桌面應用程式。翸"
7+
},
8+
"extensionActionTitle": {
9+
"message": "TimeLens 瀏覽器夥伴翸"
10+
},
11+
"extensionBridgeKey": {
12+
"message": "擴充功能橋接金鑰"
13+
},
14+
"bridgeKeyHint": {
15+
"message": "從 TimeLens 設定 > 本機 API / 擴充功能橋接取得金鑰。凫"
16+
},
17+
"save": {
18+
"message": "儲存"
19+
}
20+
}

browser-extension/i18n.js

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,48 @@ const TRANSLATIONS = {
6161
bridgeKeySaved: "扩展网桥密钥已保存。",
6262
bridgeKeyCleared: "扩展网桥密钥已清除。",
6363
},
64+
"zh-TW": {
65+
connection: "桌面端連線",
66+
checking: "檢查中",
67+
connected: "已連線",
68+
offline: "離線",
69+
today: "TimeLens 今日資料",
70+
refresh: "重新整理",
71+
recentSessions: "最近分頁工作階段",
72+
noActiveTab: "目前沒有活動分頁",
73+
noData: "暫無資料",
74+
noUsage: "本機 API 尚未回傳應用程式使用資料",
75+
noSessions: "尚無瀏覽器工作階段記錄",
76+
browserCompanion: "瀏覽器夥伴",
77+
subtitle: "不需開啟桌面端,也能查看本機狀態與最近瀏覽器工作階段。",
78+
reachable: "桌面端已可透過 localhost 連線。{{version}},{{focus}}。",
79+
unreachable: "目前無法連線到 127.0.0.1:49152 上的 TimeLens 桌面端。",
80+
focusOn: "專注模式已開啟",
81+
focusOff: "專注模式已關閉",
82+
unknownVersion: "未知版本",
83+
untitledTab: "未命名分頁",
84+
activeTab: "活動分頁",
85+
unknownSite: "未知網站",
86+
extensionDisabled: "桌面端已關閉瀏覽器同步。",
87+
extensionBridgeKey: "擴充功能橋接金鑰",
88+
bridgeKeyHint: "從 TimeLens 設定 > 本機 API / 擴充功能橋接取得金鑰。",
89+
bridgeKeyPlaceholder: "貼上從 TimeLens 設定取得的擴充功能橋接金鑰",
90+
save: "儲存",
91+
saveOrUpdate: "儲存/更新",
92+
bridgeKeySaved: "擴充功能橋接金鑰已儲存。",
93+
bridgeKeyCleared: "擴充功能橋接金鑰已清除。",
94+
},
6495
};
6596

6697
export function getLocale() {
6798
const raw = (globalThis.chrome?.i18n?.getUILanguage?.() || navigator.language || "en").toLowerCase();
68-
if (raw.startsWith("zh")) {
69-
return "zh-CN";
70-
}
99+
if (raw === "zh-tw" || raw === "zh-hk" || raw === "zh-mo" || raw === "zh-hant") return "zh-TW";
100+
if (raw.startsWith("zh")) return "zh-CN";
101+
if (raw.startsWith("ja")) return "ja";
102+
if (raw.startsWith("ko")) return "ko";
103+
if (raw.startsWith("fr")) return "fr";
104+
if (raw.startsWith("de")) return "de";
105+
if (raw.startsWith("es")) return "es";
71106
return "en";
72107
}
73108

generate-msix-icons.mjs

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { fileURLToPath } from 'url';
1111

1212
const __filename = fileURLToPath(import.meta.url);
1313
const __dirname = path.dirname(__filename);
14+
const workspaceRoot = __dirname;
1415

1516
const ICON_SPECS = [
1617
{ name: 'Square44x44Logo.png', size: 44 },
@@ -21,32 +22,11 @@ const ICON_SPECS = [
2122
{ name: 'StoreLogo.png', size: 50 }
2223
];
2324

24-
async function processIcon(sourceData, metadata, spec) {
25-
// Copy the data to avoid mutating the original
26-
const data = Buffer.from(sourceData);
27-
28-
// Process pixels - remove blue background
29-
for (let i = 0; i < data.length; i += 4) {
30-
const r = data[i];
31-
const g = data[i + 1];
32-
const b = data[i + 2];
33-
34-
// If this pixel is part of the blue background, make it transparent
35-
if (b > r + 20 && b > g + 20 && (r + g + b) < 300) {
36-
data[i + 3] = 0; // Set alpha to 0 (transparent)
37-
} else {
38-
data[i + 3] = 255; // Set alpha to 255 (opaque)
39-
}
40-
}
41-
42-
// Create processed image
43-
let image = sharp(data, {
44-
raw: {
45-
width: metadata.width,
46-
height: metadata.height,
47-
channels: 4
48-
}
49-
});
25+
const TASKBAR_TARGET_SIZES = [16, 20, 24, 30, 32, 36, 40, 44, 48, 60, 64, 72, 80, 96, 256];
26+
27+
async function processIcon(sourceIconPath, spec) {
28+
// Preserve original icon style; only resize on a transparent background.
29+
let image = sharp(sourceIconPath);
5030

5131
// Resize based on spec
5232
if (spec.width && spec.height) {
@@ -67,7 +47,6 @@ async function processIcon(sourceData, metadata, spec) {
6747
}
6848

6949
async function main() {
70-
const workspaceRoot = 'c:\\Users\\seans\\Documents\\GitHub\\TimeLens';
7150
const sourceIcon = path.join(workspaceRoot, 'src-tauri', 'icons', 'icon.png');
7251
const outputDir = path.join(workspaceRoot, 'src-tauri', 'windows', 'msix-staging', 'Assets');
7352

@@ -86,7 +65,6 @@ async function main() {
8665
// Read source icon
8766
const image = sharp(sourceIcon);
8867
const metadata = await image.metadata();
89-
const { data } = await image.raw().toBuffer({ resolveWithObject: true });
9068

9169
console.log(`Source image: ${metadata.width}x${metadata.height}`);
9270

@@ -95,7 +73,7 @@ async function main() {
9573
for (const spec of ICON_SPECS) {
9674
const outputPath = path.join(outputDir, spec.name);
9775
try {
98-
const processedImage = await processIcon(data, metadata, spec);
76+
const processedImage = await processIcon(sourceIcon, spec);
9977
await processedImage.toFile(outputPath);
10078

10179
const displayName = spec.width ?
@@ -108,9 +86,35 @@ async function main() {
10886
console.error(`✗ ${spec.name}: ${err.message}`);
10987
}
11088
}
89+
90+
for (const size of TASKBAR_TARGET_SIZES) {
91+
const names = [
92+
`Square44x44Logo.targetsize-${size}.png`,
93+
`Square44x44Logo.altform-unplated_targetsize-${size}.png`
94+
];
95+
96+
for (const name of names) {
97+
const outputPath = path.join(outputDir, name);
98+
try {
99+
await sharp(sourceIcon)
100+
.resize(size, size, {
101+
fit: 'inside',
102+
background: { r: 0, g: 0, b: 0, alpha: 0 }
103+
})
104+
.png()
105+
.toFile(outputPath);
106+
107+
console.log(`✓ ${name} (${size}x${size})`);
108+
successCount++;
109+
} catch (err) {
110+
console.error(`✗ ${name}: ${err.message}`);
111+
}
112+
}
113+
}
111114

112-
console.log(`\n✓ Successfully generated ${successCount}/${ICON_SPECS.length} MSIX icons`);
113-
console.log('✓ All icons now have transparent backgrounds');
115+
const expectedCount = ICON_SPECS.length + (TASKBAR_TARGET_SIZES.length * 2);
116+
console.log(`\n✓ Successfully generated ${successCount}/${expectedCount} MSIX icons`);
117+
console.log('✓ Generated base and unplated targetsize icons with transparent backgrounds');
114118
console.log('\nThe taskbar and Start menu will display correctly without blue backgrounds.');
115119

116120
} catch (error) {

scripts/build-msix.ps1

Lines changed: 104 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,17 @@ $OutDir = Join-Path $WindowsDir "out"
170170
$MsixPath = Join-Path $OutDir "TimeLens-$Version.msix"
171171
$SourceIcon = Join-Path $RepoRoot "src-tauri\icons\icon.png"
172172

173+
$baseAssetNames = @(
174+
"StoreLogo.png",
175+
"Square44x44Logo.png",
176+
"Square71x71Logo.png",
177+
"Square150x150Logo.png",
178+
"Wide310x150Logo.png",
179+
"Square310x310Logo.png"
180+
)
181+
182+
$PreservedAssetsDir = Join-Path $OutDir "_preserved-assets"
183+
173184
# Define publisher and display name first
174185
$publisher = $TauriConfig.bundle.publisher
175186
if ([string]::IsNullOrWhiteSpace($publisher)) {
@@ -223,6 +234,20 @@ if (!(Test-Path $ExePath)) {
223234
}
224235

225236
Write-Host "[2/5] Preparing staging directory..."
237+
if (Test-Path $PreservedAssetsDir) {
238+
Remove-Item -Recurse -Force $PreservedAssetsDir
239+
}
240+
241+
if (Test-Path $AssetsDir) {
242+
New-Item -ItemType Directory -Path $PreservedAssetsDir -Force | Out-Null
243+
foreach ($name in $baseAssetNames) {
244+
$assetPath = Join-Path $AssetsDir $name
245+
if (Test-Path $assetPath) {
246+
Copy-Item $assetPath (Join-Path $PreservedAssetsDir $name) -Force
247+
}
248+
}
249+
}
250+
226251
if (Test-Path $StagingDir) { Remove-Item -Recurse -Force $StagingDir }
227252
New-Item -ItemType Directory -Path $StagingDir | Out-Null
228253
New-Item -ItemType Directory -Path $AssetsDir -Force | Out-Null
@@ -247,34 +272,94 @@ $assetMap = @(
247272
@{ Name = "Square310x310Logo.png"; Width = 310; Height = 310 }
248273
)
249274

250-
$srcImg = [System.Drawing.Image]::FromFile($SourceIcon)
251-
try {
252-
foreach ($asset in $assetMap) {
253-
$bmp = New-Object System.Drawing.Bitmap($asset.Width, $asset.Height)
254-
try {
255-
$g = [System.Drawing.Graphics]::FromImage($bmp)
275+
# Taskbar/jump-list icons: unplated targetsize variants avoid Windows adding a background plate.
276+
$taskbarTargetSizes = @(16, 20, 24, 30, 32, 36, 40, 44, 48, 60, 64, 72, 80, 96, 256)
277+
278+
$hasPreservedBaseAssets = $true
279+
foreach ($name in $baseAssetNames) {
280+
if (!(Test-Path (Join-Path $PreservedAssetsDir $name))) {
281+
$hasPreservedBaseAssets = $false
282+
break
283+
}
284+
}
285+
286+
if ($hasPreservedBaseAssets) {
287+
Write-Host "[2.5/5] Reusing existing MSIX base assets to preserve icon style..."
288+
foreach ($name in $baseAssetNames) {
289+
Copy-Item (Join-Path $PreservedAssetsDir $name) (Join-Path $AssetsDir $name) -Force
290+
}
291+
} else {
292+
Write-Host "[2.5/5] Generating MSIX base assets from src-tauri/icons/icon.png..."
293+
$srcImg = [System.Drawing.Image]::FromFile($SourceIcon)
294+
try {
295+
foreach ($asset in $assetMap) {
296+
$bmp = New-Object System.Drawing.Bitmap($asset.Width, $asset.Height)
256297
try {
257-
$g.Clear([System.Drawing.Color]::Transparent)
258-
$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
259-
$g.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
260-
$g.CompositingQuality = [System.Drawing.Drawing2D.CompositingQuality]::HighQuality
261-
$g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality
262-
$g.DrawImage($srcImg, 0, 0, $asset.Width, $asset.Height)
298+
$g = [System.Drawing.Graphics]::FromImage($bmp)
299+
try {
300+
$g.Clear([System.Drawing.Color]::Transparent)
301+
$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
302+
$g.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
303+
$g.CompositingQuality = [System.Drawing.Drawing2D.CompositingQuality]::HighQuality
304+
$g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality
305+
$g.DrawImage($srcImg, 0, 0, $asset.Width, $asset.Height)
306+
}
307+
finally {
308+
$g.Dispose()
309+
}
310+
311+
$outPath = Join-Path $AssetsDir $asset.Name
312+
$bmp.Save($outPath, [System.Drawing.Imaging.ImageFormat]::Png)
263313
}
264314
finally {
265-
$g.Dispose()
315+
$bmp.Dispose()
266316
}
267-
268-
$outPath = Join-Path $AssetsDir $asset.Name
269-
$bmp.Save($outPath, [System.Drawing.Imaging.ImageFormat]::Png)
270317
}
271-
finally {
272-
$bmp.Dispose()
318+
}
319+
finally {
320+
$srcImg.Dispose()
321+
}
322+
}
323+
324+
$taskbarSourceIcon = Join-Path $AssetsDir "Square44x44Logo.png"
325+
if (!(Test-Path $taskbarSourceIcon)) {
326+
throw "Taskbar source icon not found: $taskbarSourceIcon"
327+
}
328+
329+
$taskbarSrcImg = [System.Drawing.Image]::FromFile($taskbarSourceIcon)
330+
try {
331+
foreach ($size in $taskbarTargetSizes) {
332+
foreach ($name in @("Square44x44Logo.targetsize-$size.png", "Square44x44Logo.altform-unplated_targetsize-$size.png")) {
333+
$bmp = New-Object System.Drawing.Bitmap($size, $size)
334+
try {
335+
$g = [System.Drawing.Graphics]::FromImage($bmp)
336+
try {
337+
$g.Clear([System.Drawing.Color]::Transparent)
338+
$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
339+
$g.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
340+
$g.CompositingQuality = [System.Drawing.Drawing2D.CompositingQuality]::HighQuality
341+
$g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality
342+
$g.DrawImage($taskbarSrcImg, 0, 0, $size, $size)
343+
}
344+
finally {
345+
$g.Dispose()
346+
}
347+
348+
$outPath = Join-Path $AssetsDir $name
349+
$bmp.Save($outPath, [System.Drawing.Imaging.ImageFormat]::Png)
350+
}
351+
finally {
352+
$bmp.Dispose()
353+
}
273354
}
274355
}
275356
}
276357
finally {
277-
$srcImg.Dispose()
358+
$taskbarSrcImg.Dispose()
359+
}
360+
361+
if (Test-Path $PreservedAssetsDir) {
362+
Remove-Item -Recurse -Force $PreservedAssetsDir
278363
}
279364

280365
Write-Host "[3/5] Resolving MakeAppx.exe..."
-12 Bytes
-386 Bytes
883 Bytes
1.25 KB
1.67 KB

0 commit comments

Comments
 (0)