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
4 changes: 4 additions & 0 deletions apps/mint/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ API `https://mint-api.juw12.workers.dev/api/health`
formulas follow the renamed tabs.
- **Links pick the language (3.5.1).** Add `?lang=en|id|zh|es` to any Mint link (Budget, the marketplace, the
legal pages) and it opens in that language without changing the reader's saved choice.
- **Studio understands more ways of saying it (3.5.5).** A 55-command probe across English, Indonesian, Chinese and
Spanish now passes in full: `usa pesos mexicanos`, `用人民币`, `改成蓝色主题`, `换成深色主题`, `cambia el título a …`,
`ubah judul jadi …` and `buang kolom …` all work. “Budget” alone no longer outranks the real subject:
`旅行预算`, `presupuesto de viaje` and `wedding budget` give the trip or wedding template.
- **Every Studio reply, every language (3.5.4).** The rarer replies are translated too (`列“供应商”已存在。`,
`Rumus salah: kolom [Foo] tidak ada.`, `Ya hay otra columna llamada “Precio”.`), Indonesian gets highlights and
card words (`sorot Laba kurang dari 0 merah`, `rata-rata Jumlah`), and the “didn’t understand” hint suggests
Expand Down
2 changes: 1 addition & 1 deletion apps/mint/desktop/mint.spec
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import os
import sys

DESKTOP = os.path.dirname(os.path.abspath(SPEC)) # noqa: F821 (provided by PyInstaller)
VERSION = os.environ.get("MINT_VERSION", "3.5.4")
VERSION = os.environ.get("MINT_VERSION", "3.5.5")
VERSION_FILE = os.environ.get("MINT_VERSION_FILE") or None
ICON = os.environ.get("MINT_ICON") or None
IS_WIN = sys.platform == "win32"
Expand Down
2 changes: 1 addition & 1 deletion apps/mint/desktop/mint_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import urllib.request
import webbrowser

VERSION = "3.5.4"
VERSION = "3.5.5"
TITLE = "Mint"
APP_URL = os.environ.get("MINT_DESKTOP_URL") or "https://juw12.github.io/projects/mint/"
DEFAULT_SIZE = (1280, 860)
Expand Down
17 changes: 17 additions & 0 deletions apps/mint/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,19 @@ def seed_checks():
zhColumnFirst: C.applyTweak(budget, "Actual 小于 0 标红").spec.rules.slice(-1)
.map(function (k) { return k.column + k.op + k.value + ":" + k.style; })[0],
esThemeWord: C.applyTweak(budget, "cambia el tema a medianoche").spec.theme,
// 3.5.5: "budget" alone is a modifier; the specific template wins
budgetModifier: ["trip plan and budget", "旅行预算", "presupuesto de viaje", "wedding budget", "monthly budget", "我的月度预算"]
.map(function (p) { return C.generate(p).spec.blueprint; }),
// 3.5.5: more natural phrasings
phrasings: [
C.applyTweak(budget, "usa pesos mexicanos").spec.currency,
C.applyTweak(budget, "用人民币").spec.currency,
C.applyTweak(budget, "改成蓝色主题").spec.theme,
C.applyTweak(budget, "换成深色主题").spec.theme,
C.applyTweak(budget, "cambia el título a Mi presupuesto").spec.title,
C.applyTweak(budget, "ubah judul jadi Anggaranku").spec.title,
C.applyTweak(budget, "buang kolom Planned").spec.sheet.columns.some(function (c) { return c.name === "Planned"; })
],
enStill: C.applyTweak(budget, "warnai Actual below 0 red").spec.rules.slice(-1)
.map(function (k) { return k.column + k.op + k.value + ":" + k.style; })[0]
};
Expand Down Expand Up @@ -402,6 +415,10 @@ def js_checks():
check(intl["oneRow"] == [1, 1, 1, 1], "add a row without a number works in en/zh/es/id " + str(intl["oneRow"]))
check(intl["zhColumnFirst"] == "Actual<0:bad", "zh column-first highlight 标红 " + str(intl["zhColumnFirst"]))
check(intl["esThemeWord"] == "midnight", "es theme word medianoche " + str(intl["esThemeWord"]))
check(intl["budgetModifier"] == ["travel", "travel", "travel", "event", "budget", "budget"],
"budget as a modifier gives way to trip/wedding templates " + str(intl["budgetModifier"]))
check(intl["phrasings"] == ["MXN", "CNY", "ocean", "midnight", "Mi presupuesto", "Anggaranku", False],
"3.5.5 phrasings (usa pesos, 用人民币, 改成蓝色主题, 换成深色主题, cambia el título, ubah judul, buang kolom) " + str(intl["phrasings"]))
check(out["diffRows"] == [p[0] - p[1] for p in pairs], "Diff column evaluates per row")

f = out["formulas"]
Expand Down
2 changes: 1 addition & 1 deletion apps/mint/web/budget/js/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
(function (root) {
'use strict';
const K = (root.MintBudget = root.MintBudget || {});
K.VERSION = '3.5.4';
K.VERSION = '3.5.5';

/** Compare dotted versions numerically: 1, 0 or -1 ("1.10.0" is newer than "1.9.9"). */
K.compareVersions = function (a, b) {
Expand Down
2 changes: 1 addition & 1 deletion apps/mint/web/budget/sw.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Mint Budget service worker: network-first app shell so updates land immediately, cache as offline fallback.
* Scope is budget/ only; Mint Templates (../app.html) has its own worker at ../sw.js. */
const CACHE = 'mint-budget-v19';
const CACHE = 'mint-budget-v20';
// Caches this worker owns: its own generations, plus the ones versions before Mint 3.0 left behind.
// Never touch other caches: every app on this origin shares one CacheStorage.
const OWN_CACHE = /^(mint-budget-v|kitty-v)/;
Expand Down
6 changes: 5 additions & 1 deletion apps/mint/web/budget/version.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"version": "3.5.4",
"version": "3.5.5",
"released": "2026-11-09",
"notes": {
"en": [
"Templates Studio understands more ways of saying things: “use Mexican pesos”, “change the title to …”, colour-first themes like 改成蓝色主题, “buang kolom …”, plus “add a row” and column-first highlights in every language. Asking for a “trip budget” or “wedding budget” now gives the trip or wedding template instead of a plain monthly budget.",
"Templates Studio answers every message in your language, including “that column already exists” and formula errors, and understands Indonesian highlights like “sorot Laba kurang dari 0 merah”.",
"Templates Studio answers fully in your language: theme names, column types and the dashboard cards a command adds (like 数量合计 or Promedio de cantidad) no longer slip into English.",
"Templates come out in your language: a prompt in Indonesian, Chinese or Spanish gives column names, dropdowns, cards and sample rows in that language, with every formula still working.",
Expand All @@ -13,6 +14,7 @@
"Templates and the Marketplace now speak Chinese and Spanish too, and downloaded .xlsx files use your language for tabs and tips."
],
"id": [
"Studio Template paham lebih banyak cara bicara: “buang kolom …”, “ubah judul jadi …”, “tambah baris”, plus tema dan mata uang yang disebut langsung dalam bahasa Mandarin dan Spanyol. Minta “anggaran liburan” atau “anggaran pernikahan” kini memberi template perjalanan atau pernikahan, bukan anggaran bulanan biasa.",
"Studio Template menjawab setiap pesan dalam bahasamu, termasuk “kolom sudah ada” dan kesalahan rumus, dan kini paham perintah sorot seperti “sorot Laba kurang dari 0 merah”.",
"Studio Template menjawab sepenuhnya dalam bahasamu: nama tema, jenis kolom, dan kartu dashboard yang ditambahkan lewat perintah tidak lagi muncul dalam bahasa Inggris.",
"Template kini keluar dalam bahasamu: perintah dalam Bahasa Indonesia, Mandarin, atau Spanyol menghasilkan nama kolom, pilihan, kartu, dan contoh baris dalam bahasa itu, dengan semua rumus tetap berjalan.",
Expand All @@ -23,6 +25,7 @@
"Template dan Marketplace kini juga berbahasa Mandarin dan Spanyol, dan file .xlsx yang diunduh memakai bahasamu untuk tab dan petunjuk."
],
"zh": [
"模板工作室能听懂更多说法:“改成蓝色主题”“换成深色主题”“用人民币”“加一行”,以及“利润 小于 0 标红”这样先说列名的高亮。 说“旅行预算”或“婚礼预算”时,会给出旅行或婚礼模板,而不是普通的月度预算。",
"模板工作室的每条回复都使用你的语言,包括“列已存在”和公式错误提示;也能听懂印尼语的高亮指令。",
"模板工作室完全用你的语言回复:主题名称、列类型以及通过指令添加的仪表盘卡片(例如“数量合计”)不再夹杂英文。",
"模板现在用你的语言生成:用中文、印尼语或西班牙语描述,列名、下拉选项、汇总卡片和示例行都会是该语言,所有公式照常运行。",
Expand All @@ -33,6 +36,7 @@
"模板和市场现在也支持中文和西班牙语,下载的 .xlsx 文件的工作表名称和提示也使用你的语言。"
],
"es": [
"El Estudio de plantillas entiende más formas de decirlo: “usa pesos mexicanos”, “cambia el título a …”, “añade una fila” y temas como “cambia el tema a medianoche”. Pedir un “presupuesto de viaje” o “de boda” ahora da la plantilla de viaje o de boda, no un presupuesto mensual.",
"El estudio de Plantillas responde cada mensaje en tu idioma, incluidos «la columna ya existe» y los errores de fórmula, y entiende resaltados en indonesio.",
"El estudio de Plantillas responde del todo en tu idioma: los nombres de tema, los tipos de columna y las tarjetas del panel que añade una orden (como «Promedio de cantidad») ya no salen en inglés.",
"Las plantillas salen en tu idioma: una petición en español, chino o indonesio da nombres de columna, listas, tarjetas y filas de ejemplo en ese idioma, y todas las fórmulas siguen funcionando.",
Expand Down
37 changes: 31 additions & 6 deletions apps/mint/web/js/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -466,17 +466,35 @@
return best;
}

var BUDGET_MODIFIERS = ["budget", "anggaran", "预算", "presupuesto"];

function scoreBlueprints(text) {
var lower = " " + text.toLowerCase() + " ";
return BLUEPRINTS.map(function (bp) {
var ranked = BLUEPRINTS.map(function (bp) {
var score = 0;
bp.keywords.concat(BLUEPRINT_KEYWORDS_INTL[bp.id] || []).forEach(function (k) {
if (lower.indexOf(k) !== -1) {
score += k.length > 5 || /[\u3400-\u9fff]/.test(k) ? 3 : 2;
}
});
return { bp: bp, score: score };
}).sort(function (a, b) {
});
// "budget" on its own is a modifier: "trip budget", "婚礼预算", "presupuesto de viaje" want the trip or
// wedding template, so a budget score made only of that word gives way to any specific match
var budget = ranked.filter(function (r) { return r.bp.id === "budget"; })[0];
if (budget && budget.score > 0) {
var modifierScore = 0;
BUDGET_MODIFIERS.forEach(function (word) {
if (lower.indexOf(word) !== -1) {
modifierScore += word.length > 5 || /[\u3400-\u9fff]/.test(word) ? 3 : 2;
}
});
var otherMatch = ranked.some(function (r) { return r.bp.id !== "budget" && r.score > 0; });
if (otherMatch && budget.score <= modifierScore) {
budget.score = 0.5;
}
}
return ranked.sort(function (a, b) {
return b.score - a.score;
});
}
Expand Down Expand Up @@ -1634,12 +1652,16 @@
if ((m = /^(?:把|将)?\s*(?:货币|币种)\s*(?:改为|改成|换成|设为|为|用)?\s*:?\s*(.+)$/.exec(s))) {
return "currency " + m[1];
}
if ((m = /^(?:使用|改用|换成)\s*(.+)$/.exec(s)) && detectCurrency(m[1])) {
if ((m = /^(?:使用|改用|换成|换用|用)\s*(.+)$/.exec(s)) && detectCurrency(m[1])) {
return "currency " + m[1];
}
if ((m = /^(?:把|将)?\s*(?:主题|配色|颜色|风格)\s*(?:改为|改成|换成|设为|为|用)?\s*:?\s*(.+)$/.exec(s))) {
return "theme " + m[1];
}
// colour first: "改成蓝色主题", "换成深色主题", "用绿色的配色"
if ((m = /^(?:改成|换成|改为|换个|换一个|用|设为|来个)\s*(.+?)\s*(?:的)?\s*(?:主题|配色|风格)$/.exec(s)) && detectTheme(m[1])) {
return "theme " + m[1];
}
if ((m = /^(?:把|将)?\s*(?:标题|模板名称|模板名|表名)\s*(?:改为|改成|设为|为|是)?\s*:?\s*(.+)$/.exec(s)) ||
(m = /^(?:命名为|重命名模板为)\s*:?\s*(.+)$/.exec(s))) {
return "title " + m[1];
Expand Down Expand Up @@ -1673,7 +1695,7 @@
if ((m = new RegExp("^(?:elimina|eliminar|quita|quitar|borra|borrar|suprime|suprimir)\\s+" + art + "(?:columna\\s+|campo\\s+)?(.+)$", "i").exec(s))) {
return "remove column " + m[1];
}
if ((m = /^(?:t[íi]tulo|ll[áa]mal[ao]|ponle\s+de\s+nombre|renombra(?:r)?\s+la\s+(?:plantilla|hoja)\s+(?:a|como))\s*:?\s+(.+)$/i.exec(s))) {
if ((m = /^(?:t[íi]tulo|ll[áa]mal[ao]|ponle\s+de\s+nombre|renombra(?:r)?\s+la\s+(?:plantilla|hoja)\s+(?:a|como)|cambia(?:r)?\s+el\s+t[íi]tulo\s+(?:a|por))\s*:?\s+(.+)$/i.exec(s))) {
return "title " + m[1];
}
if ((m = /^(?:renombra(?:r)?|cambia(?:r)?\s+el\s+nombre\s+de)\s+(?:la\s+columna\s+|el\s+campo\s+|columna\s+)?(.+?)\s+(?:a|por|como)\s+(.+)$/i.exec(s))) {
Expand All @@ -1682,6 +1704,9 @@
if ((m = /^(?:(?:cambia(?:r)?|pon(?:er)?|usa(?:r)?)\s+(?:la\s+)?)?(?:moneda|divisa)\s*(?:a\s+|en\s+|:)?\s*(.+)$/i.exec(s))) {
return "currency " + m[1];
}
if ((m = /^(?:usa(?:r)?|paga(?:r)?\s+en|cambia(?:r)?\s+a|p[áa]sa(?:lo)?\s+a)\s+(.+)$/i.exec(s)) && detectCurrency(m[1])) {
return "currency " + m[1];
}
if ((m = /^(?:(?:cambia(?:r)?|pon(?:er)?|usa(?:r)?)\s+(?:el\s+)?)?(?:tema|estilo|color)\b\s*(?:a\s+|en\s+|:)?\s*(.+)$/i.exec(s))) {
return "theme " + m[1];
}
Expand Down Expand Up @@ -1793,7 +1818,7 @@
return "Added column \u201c" + col.name + "\u201d (" + col.type + ").";
}
// remove column
if ((m = /^(?:remove|delete|drop|hapus)\s+(?:the\s+)?(?:column|kolom)?\s*(.+)$/i.exec(t))) {
if ((m = /^(?:remove|delete|drop|hapus(?:kan)?|buang|hilangkan)\s+(?:the\s+)?(?:column|kolom)?\s*(.+)$/i.exec(t))) {
var target = findColumn(spec, m[1]);
if (!target) {
return "No column named \u201c" + m[1].trim() + "\u201d.";
Expand All @@ -1813,7 +1838,7 @@
return "Removed \u201c" + target.name + "\u201d.";
}
// rename template
if ((m = /^(?:call it|title|name it|rename (?:the )?(?:template|sheet) to|judul)\s*:?\s+(.+)$/i.exec(t))) {
if ((m = /^(?:call it|title|name it|rename (?:the )?(?:template|sheet) to|change (?:the )?title to|(?:ubah|ganti) judul(?:nya)?(?: jadi| menjadi| ke)?|judul)\s*:?\s+(.+)$/i.exec(t))) {
spec.title = clampText(m[1].replace(/^["'\u201c]|["'\u201d]$/g, ""), 70);
return "Renamed the template to \u201c" + spec.title + "\u201d.";
}
Expand Down
2 changes: 1 addition & 1 deletion apps/mint/web/sw.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Mint Templates service worker — app shell cache. API calls (api/...) always go to the network.
* Mint Budget (budget/) has its own worker with the narrower scope budget/, so it is not cached here. */
var CACHE = "mint-v3.5.4";
var CACHE = "mint-v3.5.5";
var SHELL = [
"./", "index.html", "app.html", "web.html", "mobile.html", "privacy.html", "terms.html", "delete-account.html", "app.css",
"js/locale.js", "js/mint-cloud.js", "js/core.js", "js/xlsx.js", "js/guides.js", "js/store.js", "js/i18n-more.js", "js/i18n.js", "js/app.js",
Expand Down
Loading