From 005761a4fa0e5b03f5af869274bc85f8bab347d6 Mon Sep 17 00:00:00 2001
From: wangzhibo <wangzhibo@shsening.com>
Date: 星期四, 16 七月 2026 08:16:58 +0800
Subject: [PATCH] first
---
config/i18n/zh.json | 305 ++++
config/items.json | 1202 ++++++++++++++++
js/i18n.js | 54
assets/tabs/dry.svg | 5
js/data.js | 51
config/i18n/en.json | 305 ++++
assets/tabs/hazardous-gray.png | 0
assets/tabs/recyclable.svg | 5
assets/tabs/wet.svg | 5
index.html | 123 +
assets/tabs/dry-gray.png | 0
js/app.js | 353 ++++
scripts/generate_items.py | 417 +++++
assets/logo.png | 0
assets/tabs/wet.png | 0
assets/tabs/recyclable.png | 0
assets/tabs/recyclable-gray.png | 0
assets/icon-logo.svg | 6
assets/tabs/wet-gray.png | 0
config/i18n/ja.json | 305 ++++
assets/tabs/hazardous.png | 0
README.md | 4
config/categories.json | 82 +
assets/tabs/hazardous.svg | 6
js/storage.js | 22
config/i18n/ko.json | 305 ++++
css/styles.css | 668 +++++++++
assets/tabs/dry.png | 0
28 files changed, 4,219 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 769c464..e69de29 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +0,0 @@
-## garbage-classfication
-
-鍏紬鍙烽〉闈�-鍨冨溇鍒嗙被
-
diff --git a/assets/icon-logo.svg b/assets/icon-logo.svg
new file mode 100644
index 0000000..442325c
--- /dev/null
+++ b/assets/icon-logo.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none">
+ <rect width="48" height="48" rx="10" fill="#0071BC"/>
+ <path d="M14 32V18h4l6 10 6-10h4v14h-3.5V23l-5.5 9h-2l-5.5-9v9H14z" fill="#fff"/>
+ <circle cx="36" cy="14" r="4" fill="#8B4513"/>
+ <circle cx="12" cy="14" r="4" fill="#E60012"/>
+</svg>
diff --git a/assets/logo.png b/assets/logo.png
new file mode 100644
index 0000000..733e599
--- /dev/null
+++ b/assets/logo.png
Binary files differ
diff --git a/assets/tabs/dry-gray.png b/assets/tabs/dry-gray.png
new file mode 100644
index 0000000..06443f8
--- /dev/null
+++ b/assets/tabs/dry-gray.png
Binary files differ
diff --git a/assets/tabs/dry.png b/assets/tabs/dry.png
new file mode 100644
index 0000000..0a3ca3f
--- /dev/null
+++ b/assets/tabs/dry.png
Binary files differ
diff --git a/assets/tabs/dry.svg b/assets/tabs/dry.svg
new file mode 100644
index 0000000..1c7fb9b
--- /dev/null
+++ b/assets/tabs/dry.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
+ <rect x="8" y="10" width="16" height="16" rx="2" stroke="#fff" stroke-width="2" fill="none"/>
+ <path d="M8 16h16" stroke="#fff" stroke-width="1.5"/>
+ <path d="M14 10V8M18 10V8" stroke="#fff" stroke-width="2"/>
+</svg>
diff --git a/assets/tabs/hazardous-gray.png b/assets/tabs/hazardous-gray.png
new file mode 100644
index 0000000..34f1d1c
--- /dev/null
+++ b/assets/tabs/hazardous-gray.png
Binary files differ
diff --git a/assets/tabs/hazardous.png b/assets/tabs/hazardous.png
new file mode 100644
index 0000000..434b8c1
--- /dev/null
+++ b/assets/tabs/hazardous.png
Binary files differ
diff --git a/assets/tabs/hazardous.svg b/assets/tabs/hazardous.svg
new file mode 100644
index 0000000..9c6b3da
--- /dev/null
+++ b/assets/tabs/hazardous.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
+ <rect x="10" y="6" width="12" height="20" rx="2" stroke="#fff" stroke-width="2" fill="none"/>
+ <path d="M14 6V4h4v2" stroke="#fff" stroke-width="2"/>
+ <path d="M13 14h6M13 18h6M13 22h4" stroke="#fff" stroke-width="1.5"/>
+ <circle cx="16" cy="12" r="2" fill="#fff"/>
+</svg>
diff --git a/assets/tabs/recyclable-gray.png b/assets/tabs/recyclable-gray.png
new file mode 100644
index 0000000..47d2dc7
--- /dev/null
+++ b/assets/tabs/recyclable-gray.png
Binary files differ
diff --git a/assets/tabs/recyclable.png b/assets/tabs/recyclable.png
new file mode 100644
index 0000000..fe0aad1
--- /dev/null
+++ b/assets/tabs/recyclable.png
Binary files differ
diff --git a/assets/tabs/recyclable.svg b/assets/tabs/recyclable.svg
new file mode 100644
index 0000000..ca0d06f
--- /dev/null
+++ b/assets/tabs/recyclable.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
+ <path d="M8 28V12l8-6 8 6v16H8z" stroke="#fff" stroke-width="2" fill="none"/>
+ <path d="M13 20h6v8h-6z" fill="#fff" opacity="0.8"/>
+ <path d="M4 28h24" stroke="#fff" stroke-width="2"/>
+</svg>
diff --git a/assets/tabs/wet-gray.png b/assets/tabs/wet-gray.png
new file mode 100644
index 0000000..17c959a
--- /dev/null
+++ b/assets/tabs/wet-gray.png
Binary files differ
diff --git a/assets/tabs/wet.png b/assets/tabs/wet.png
new file mode 100644
index 0000000..b2beb87
--- /dev/null
+++ b/assets/tabs/wet.png
Binary files differ
diff --git a/assets/tabs/wet.svg b/assets/tabs/wet.svg
new file mode 100644
index 0000000..3b67df5
--- /dev/null
+++ b/assets/tabs/wet.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
+ <ellipse cx="16" cy="20" rx="10" ry="6" stroke="#fff" stroke-width="2" fill="none"/>
+ <path d="M10 14c0-4 2.5-8 6-8s6 4 6 8" stroke="#fff" stroke-width="2" fill="none"/>
+ <path d="M12 22c2 2 6 2 8 0" stroke="#fff" stroke-width="1.5"/>
+</svg>
diff --git a/config/categories.json b/config/categories.json
new file mode 100644
index 0000000..0e87fb5
--- /dev/null
+++ b/config/categories.json
@@ -0,0 +1,82 @@
+[
+ {
+ "id": "recyclable",
+ "color": "#104883",
+ "icon": "assets/tabs/recyclable.png",
+ "iconInactive": "assets/tabs/recyclable-gray.png",
+ "nameKey": "cat.recyclable",
+ "descKey": "cat.recyclable.desc",
+ "standardKey": "cat.recyclable.standard",
+ "disposalTemplate": {
+ "suggestKey": "disposal.suggest.recyclable",
+ "line1Key": "disposal.line1.recyclable",
+ "line2Key": "disposal.line2.recyclable",
+ "tipsKeys": [
+ "disposal.tip1.recyclable",
+ "disposal.tip2.recyclable",
+ "disposal.tip3.recyclable",
+ "disposal.tip4.recyclable"
+ ]
+ }
+ },
+ {
+ "id": "hazardous",
+ "color": "#e53122",
+ "icon": "assets/tabs/hazardous.png",
+ "iconInactive": "assets/tabs/hazardous-gray.png",
+ "nameKey": "cat.hazardous",
+ "descKey": "cat.hazardous.desc",
+ "standardKey": "cat.hazardous.standard",
+ "disposalTemplate": {
+ "suggestKey": "disposal.suggest.hazardous",
+ "line1Key": "disposal.line1.hazardous",
+ "line2Key": "disposal.line2.hazardous",
+ "tipsKeys": [
+ "disposal.tip1.hazardous",
+ "disposal.tip2.hazardous",
+ "disposal.tip3.hazardous",
+ "disposal.tip4.hazardous"
+ ]
+ }
+ },
+ {
+ "id": "wet",
+ "color": "#694539",
+ "icon": "assets/tabs/wet.png",
+ "iconInactive": "assets/tabs/wet-gray.png",
+ "nameKey": "cat.wet",
+ "descKey": "cat.wet.desc",
+ "standardKey": "cat.wet.standard",
+ "disposalTemplate": {
+ "suggestKey": "disposal.suggest.wet",
+ "line1Key": "disposal.line1.wet",
+ "line2Key": "disposal.line2.wet",
+ "tipsKeys": [
+ "disposal.tip1.wet",
+ "disposal.tip2.wet",
+ "disposal.tip3.wet",
+ "disposal.tip4.wet"
+ ]
+ }
+ },
+ {
+ "id": "dry",
+ "color": "#312d2a",
+ "icon": "assets/tabs/dry.png",
+ "iconInactive": "assets/tabs/dry-gray.png",
+ "nameKey": "cat.dry",
+ "descKey": "cat.dry.desc",
+ "standardKey": "cat.dry.standard",
+ "disposalTemplate": {
+ "suggestKey": "disposal.suggest.dry",
+ "line1Key": "disposal.line1.dry",
+ "line2Key": "disposal.line2.dry",
+ "tipsKeys": [
+ "disposal.tip1.dry",
+ "disposal.tip2.dry",
+ "disposal.tip3.dry",
+ "disposal.tip4.dry"
+ ]
+ }
+ }
+]
diff --git a/config/i18n/en.json b/config/i18n/en.json
new file mode 100644
index 0000000..a1e4b11
--- /dev/null
+++ b/config/i18n/en.json
@@ -0,0 +1,305 @@
+{
+ "page.title": "Shanghai Waste Sorting Guide",
+ "header.title": "How to Sort Daily Waste in Shanghai?",
+ "btn.home": "Home",
+ "btn.query": "Search",
+ "btn.voice": "Hold to Speak",
+ "btn.standard": "Disposal Rules",
+ "btn.home.short": "Home",
+ "search.placeholder": "Enter waste name",
+ "search.notFoundHint": "I couldn't find an exact match. How about these?",
+ "search.referenceHint": "Please refer to the following categories.",
+ "search.noResults": "No results found. Please try another keyword.",
+ "lang.zh": "Chinese",
+ "lang.en": "English",
+ "lang.ko": "Korean",
+ "footer.copyright": "Shanghai Jingshen Copyright 漏 2026",
+ "welcome.title": "Friendly Reminder",
+ "welcome.p1": "1. Please enter the standard Chinese name of the waste (including material), such as glass bottle, disposable plastic cup, ceramic bowl, etc.",
+ "welcome.p2": "2. The specific classification standards for household waste sorting are refined and adjusted based on economic and social development, waste characteristics, and treatment methods.",
+ "welcome.p3": "3. This query system is for reference only. Please follow the requirements of local professional management authorities.",
+ "welcome.confirm": "Got it",
+ "disposal.suggestLabel": "Suggested disposal to:",
+ "disposal.tipsTitle": "Did You Know?",
+ "cat.recyclable": "Recyclables",
+ "cat.recyclable.desc": "Waste paper, waste plastic, waste glass products, waste metal, waste textiles and other household waste suitable for recycling and reuse.",
+ "cat.recyclable.standard": "1. Handle gently.\n2. Keep clean and dry to avoid contamination.\n3. Paper should be flat and dry.\n4. Plastic should be rinsed and dried.\n5. Empty and clean 3D packaging, then flatten.\n6. Wrap items with sharp edges.\n7. Metal should be rinsed and flattened.\n8. Textiles should be washed, dried, and folded.",
+ "cat.hazardous": "Hazardous Waste",
+ "cat.hazardous.desc": "Household waste that poses direct or potential harm to human health or the natural environment, including waste batteries, light tubes, medicine, paint and containers.",
+ "cat.hazardous.standard": "1. Handle hazardous waste gently; wrap fragile items.\n2. Keep batteries intact.\n3. Wrap light tubes to prevent breakage.\n4. Dispose medicine with packaging.\n5. Seal paint cans.\n6. Ensure safety, avoid leaks.\n7. Seal volatile items before disposal.",
+ "cat.wet": "Wet Waste",
+ "cat.wet.desc": "Perishable household waste including food scraps, leftovers, expired food, fruit peels, flowers, and herbal dregs.",
+ "cat.wet.standard": "1. Drain water before disposal.\n2. Pure liquids should go down the drain.\n3. Remove packaging from wet waste.\n4. Large bones and shells go in dry waste.\n5. Remove debris from kitchen waste.",
+ "cat.dry": "Dry Waste",
+ "cat.dry.desc": "Other household waste that is not recyclable, hazardous, or wet waste.",
+ "cat.dry.standard": "1. Drain water when possible.\n2. Hard-to-classify waste goes in dry waste.\n3. Break down large items.\n4. Disposable utensils and tissues are dry waste.\n5. Extinguish cigarette butts completely.",
+ "disposal.suggest.recyclable": "Recyclables",
+ "disposal.line1.recyclable": "Keep clean and dry to avoid contamination.",
+ "disposal.line2.recyclable": "Remove residue and flatten before disposal.",
+ "disposal.tip1.recyclable": "Recyclables can be processed into new products, saving resources.",
+ "disposal.tip2.recyclable": "Recycling one plastic bottle saves enough energy to power a 60W bulb for 3 hours.",
+ "disposal.tip3.recyclable": "Recycling one ton of paper saves 17 trees.",
+ "disposal.tip4.recyclable": "Every small act of sorting helps the circular economy.",
+ "disposal.suggest.hazardous": "Hazardous Waste",
+ "disposal.line1.hazardous": "Handle gently; wrap fragile items before disposal.",
+ "disposal.line2.hazardous": "Batteries and light tubes should remain intact.",
+ "disposal.tip1.hazardous": "Hazardous waste contains harmful substances requiring special treatment.",
+ "disposal.tip2.hazardous": "One discarded battery can contaminate 1 m虏 of land for 50 years.",
+ "disposal.tip3.hazardous": "Fluorescent tubes contain mercury; breakage pollutes air and soil.",
+ "disposal.tip4.hazardous": "Proper disposal protects our health and environment.",
+ "disposal.suggest.wet": "Wet Waste",
+ "disposal.line1.wet": "Drain water before disposal; pour pure liquids down the drain.",
+ "disposal.line2.wet": "Remove packaging from wet waste before sorting.",
+ "disposal.tip1.wet": "Wet waste can be composted into organic fertilizer.",
+ "disposal.tip2.wet": "Shanghai generates about 10,000 tons of wet waste daily.",
+ "disposal.tip3.wet": "Draining wet waste reduces leachate during processing.",
+ "disposal.tip4.wet": "Food scraps can become valuable resources through composting.",
+ "disposal.suggest.dry": "Dry Waste",
+ "disposal.line1.dry": "Drain water when possible before disposal.",
+ "disposal.line2.dry": "Hard-to-classify waste should go in dry waste.",
+ "disposal.tip1.dry": "Dry waste is mainly processed by incineration or landfill.",
+ "disposal.tip2.dry": "Reduce dry waste at the source through better sorting.",
+ "disposal.tip3.dry": "Tissues, cigarette butts, and disposable utensils are dry waste.",
+ "disposal.tip4.dry": "Better sorting makes our city more beautiful.",
+ "lang.ja": "鏃ユ湰瑾�",
+ "item.milkBox": "Milk Carton",
+ "item.plastic": "Plastic",
+ "item.glassBottle": "Glass Bottle",
+ "item.glass": "Glass",
+ "item.paper": "Paper",
+ "item.clothes": "Clothes",
+ "item.brokenGlass": "Broken Glass",
+ "item.can": "Aluminum Can",
+ "item.plasticBox": "Plastic Box",
+ "item.foamBoard": "Foam Board",
+ "item.powerBank": "Power Bank",
+ "item.shoes": "Shoes",
+ "item.paperBox": "Paper Box",
+ "item.foamBox": "Foam Box",
+ "item.glassCup": "Glass Cup",
+ "item.newspaper": "Newspaper",
+ "item.plasticCup": "Plastic Cup",
+ "item.wire": "Electric Wire",
+ "item.dataCable": "Data Cable",
+ "item.waterBottle": "Water Bottle",
+ "item.pillow": "Pillow",
+ "item.blade": "Blade",
+ "item.screw": "Screw",
+ "item.foamPlastic": "Foam Plastic",
+ "item.yogurtTetraPak": "Yogurt Tetra Pak",
+ "item.paperBag": "Paper Bag",
+ "item.cosmeticPlasticBottle": "Empty Cosmetic Plastic Bottle",
+ "item.leatherShoes": "Leather Shoes",
+ "item.cosmeticGlassBottle": "Empty Cosmetic Glass Bottle",
+ "item.wineBottle": "Wine Bottle",
+ "item.chargingCable": "Charging Cable",
+ "item.flyer": "Flyer",
+ "item.wastePlastic": "Waste Plastic",
+ "item.cigaretteBox": "Cigarette Box",
+ "item.charger": "Charger",
+ "item.book": "Books",
+ "item.beerBottle": "Beer Bottle",
+ "item.cardboardBox": "Cardboard Box",
+ "item.woodChopsticks": "Wooden Chopsticks",
+ "item.plushToy": "Plush Toy",
+ "item.bedSheet": "Bed Sheet",
+ "item.scissors": "Scissors",
+ "item.drinkPlasticBottle": "Drink Plastic Bottle",
+ "item.fabric": "Fabric",
+ "item.dehumidifierBox": "Dehumidifier Box",
+ "item.magnet": "Magnet",
+ "item.plasticWrap": "Plastic Wrap",
+ "item.quilt": "Quilt",
+ "item.tetraPak": "Tetra Pak",
+ "item.basketball": "Basketball",
+ "item.aluminumFoil": "Aluminum Foil",
+ "item.socket": "Socket",
+ "item.iron": "Iron",
+ "item.key": "Key",
+ "item.printingPaper": "Printing Paper",
+ "item.metal": "Metal",
+ "item.whitePaper": "White Paper",
+ "item.packagingBox": "Packaging Paper Box",
+ "item.plasticLid": "Plastic Lid",
+ "item.envelope": "Envelope",
+ "item.medicinePackaging": "Medicine Packaging",
+ "item.medicineBottle": "Medicine Bottle",
+ "item.lightBulb": "Light Bulb",
+ "item.paintBucket": "Paint Bucket",
+ "item.medicine": "Medicine",
+ "item.expiredMedicine": "Expired Medicine",
+ "item.rechargeableBattery": "Rechargeable Battery",
+ "item.nailPolish": "Nail Polish",
+ "item.storageBattery": "Storage Battery",
+ "item.emptyMedicineBottle": "Empty Medicine Bottle",
+ "item.hazardousWaste": "Hazardous Waste",
+ "item.expiredMedicine2": "Expired Medicine",
+ "item.wasteMedicine": "Waste Medicine",
+ "item.lightTube": "Light Tube",
+ "item.fluorescentTube": "Fluorescent Tube",
+ "item.niCdBattery": "Ni-Cd Battery",
+ "item.photo": "Photo",
+ "item.fluorescentLamp": "Fluorescent Lamp",
+ "item.hairDyeShell": "Hair Dye Shell",
+ "item.eyeDrops": "Eye Drops",
+ "item.energySavingLamp": "Energy-saving Lamp",
+ "item.insecticide": "Insecticide",
+ "item.medicineTablet": "Medicine Tablet",
+ "item.medicineTabletBox": "Medicine Tablet Box",
+ "item.oralLiquidBottle": "Oral Liquid Medicine Bottle",
+ "item.wasteMedicineBottle": "Waste Medicine Bottle",
+ "item.paint": "Paint",
+ "item.buttonBattery": "Button Battery",
+ "item.contraceptive": "Contraceptive",
+ "item.eyeDropsBottle": "Eye Drops Bottle",
+ "item.film": "Film",
+ "item.capsule": "Capsule",
+ "item.mercuryThermometer": "Mercury Thermometer",
+ "item.ratPoison": "Rat Poison",
+ "item.capsuleBlister": "Capsule Blister Pack",
+ "item.hairDyeCan": "Hair Dye Can",
+ "item.energySavingBulb": "Energy-saving Bulb",
+ "item.allExpiredMedicine": "All Types of Expired Medicine",
+ "item.incandescentBulb": "Incandescent Bulb",
+ "item.phoneBattery": "Phone Battery",
+ "item.disinfectantBottle": "Disinfectant Bottle",
+ "item.expiredTablets": "Expired Tablets",
+ "item.coldMedicine": "Cold Medicine",
+ "item.disinfectant84Bottle": "Empty 84 Disinfectant Bottle",
+ "item.nailPolishBottle": "Nail Polish Bottle",
+ "item.sprayCan": "Spray Can",
+ "item.photoNegative": "Photo Negative",
+ "item.chinesePatentMedicine": "Chinese Patent Medicine",
+ "item.filmRoll": "Film Roll",
+ "item.medicineShell": "Medicine Shell",
+ "item.mercury": "Mercury",
+ "item.photo2": "Photo",
+ "item.wastePaintBucket": "Waste Paint Bucket",
+ "item.expiredDrug": "Expired Drug",
+ "item.medicineBlister": "Medicine Blister Pack",
+ "item.cockroachMedicine": "Cockroach Medicine",
+ "item.cockroachBall": "Cockroach Ball",
+ "item.capsuleTablet": "Capsule and Tablet",
+ "item.disinfectantTablet": "Disinfectant Tablet",
+ "item.energySavingTube": "Energy-saving Tube",
+ "item.melonSeedShell": "Melon Seed Shell",
+ "item.eggShell": "Egg Shell",
+ "item.cornCob": "Corn Cob",
+ "item.eggshell": "Eggshell",
+ "item.corn": "Corn",
+ "item.walnut": "Walnut",
+ "item.peanutShell": "Peanut Shell",
+ "item.tea": "Tea Leaves",
+ "item.lobsterShell": "Lobster Shell",
+ "item.crayfish": "Crayfish",
+ "item.crabShell": "Crab Shell",
+ "item.chickenBone": "Chicken Bone",
+ "item.melonSeed": "Melon Seed",
+ "item.crabShell2": "Crab Shell",
+ "item.cookedCornCob": "Cooked Corn Cob",
+ "item.pistachioShell": "Pistachio Shell",
+ "item.crayfishShell": "Crayfish Shell",
+ "item.edamameShell": "Edamame Shell",
+ "item.shrimpShell": "Shrimp Shell",
+ "item.bananaPeel": "Banana Peel",
+ "item.watermelonRind": "Watermelon Rind",
+ "item.chestnutShell": "Chestnut Shell",
+ "item.fishBone": "Fish Bone",
+ "item.lobster": "Lobster",
+ "item.cornCore": "Corn Core",
+ "item.melonSeedPiece": "Melon Seed Piece",
+ "item.flower": "Flower",
+ "item.coffeeGrounds": "Coffee Grounds",
+ "item.porkRibs": "Pork Ribs",
+ "item.zongzi": "Zongzi",
+ "item.herbalDregs": "Herbal Medicine Dregs",
+ "item.egg": "Egg",
+ "item.crab": "Crab",
+ "item.lycheeShell": "Lychee Shell",
+ "item.peach": "Peach",
+ "item.plumPit": "Preserved Plum Pit",
+ "item.jujubePit": "Jujube Pit",
+ "item.chickenBone2": "Chicken Bone",
+ "item.expiredFood": "Expired Food",
+ "item.fishBone2": "Fish Bone",
+ "item.apple": "Apple",
+ "item.lycheePit": "Lychee Pit",
+ "item.bayberry": "Bayberry",
+ "item.watermelonSeed": "Watermelon Seed",
+ "item.chestnutShell2": "Chestnut Shell",
+ "item.cockroach2": "Cockroach",
+ "item.fruitPeel": "Fruit Peel",
+ "item.mangoPit": "Mango Pit",
+ "item.peanut": "Peanut",
+ "item.driedPeanutShell": "Dried Peanut Shell",
+ "item.biscuit": "Biscuit",
+ "item.watermelon": "Watermelon",
+ "item.freshFlower": "Fresh Flower",
+ "item.redJujubePit": "Red Jujube Pit",
+ "item.lusuji": "Sorghum",
+ "item.appleCore": "Apple Core",
+ "item.waterBambooPeel": "Water Bamboo Peel",
+ "item.bread": "Bread",
+ "item.banana": "Banana",
+ "item.teaResidue": "Tea Residue",
+ "item.plasticBag": "Plastic Bag",
+ "item.zongziLeaf": "Zongzi Leaf",
+ "item.walnutShell": "Walnut Shell",
+ "item.hair": "Hair",
+ "item.shell": "Shell",
+ "item.sanitaryPad": "Sanitary Pad",
+ "item.condom": "Condom",
+ "item.chewingGum": "Chewing Gum",
+ "item.lighter": "Lighter",
+ "item.coconutShell": "Coconut Shell",
+ "item.catLitter": "Cat Litter",
+ "item.faceMask": "Face Mask",
+ "item.tissue": "Tissue Paper",
+ "item.bigBone": "Big Bone",
+ "item.milkTeaCup": "Milk Tea Cup",
+ "item.paperTowel": "Paper Towel",
+ "item.clamShell": "Clam Shell",
+ "item.zongziLeaf2": "Zongzi Leaf",
+ "item.cornHusk": "Corn Husk",
+ "item.straw": "Straw",
+ "item.teaBag": "Tea Bag",
+ "item.sugarcanePeel": "Sugarcane Peel",
+ "item.desiccant": "Desiccant",
+ "item.disposableChopsticks": "Disposable Chopsticks",
+ "item.cornShell": "Corn Shell",
+ "item.cigarette": "Cigarette Butt",
+ "item.wetWipe": "Wet Wipe",
+ "item.durianShell": "Durian Shell",
+ "item.toiletPaper": "Toilet Paper",
+ "item.bigWalnutShell": "Big Walnut Shell",
+ "item.nail": "Nail",
+ "item.packagingBag": "Packaging Bag",
+ "item.lipstick": "Lipstick",
+ "item.disposableCup": "Disposable Cup",
+ "item.snailShell": "Snail Shell",
+ "item.toothbrush": "Toothbrush",
+ "item.takeoutBox": "Takeout Box",
+ "item.durian": "Durian",
+ "item.diaper": "Diaper",
+ "item.trashBag": "Trash Bag",
+ "item.toothpasteTube": "Toothpaste Tube",
+ "item.icePack": "Ice Pack",
+ "item.sock": "Sock",
+ "item.pen": "Pen",
+ "item.diaper2": "Diaper",
+ "item.durianPit": "Durian Pit",
+ "item.disposableLunchBox": "Disposable Lunch Box",
+ "item.teaBag2": "Tea Bag",
+ "item.mask": "Mask",
+ "item.underwear": "Underwear",
+ "item.towel": "Towel",
+ "item.diaper3": "Diaper",
+ "item.ceramicBowl": "Ceramic Bowl",
+ "item.penRefill": "Pen Refill",
+ "item.dirtyPlasticBag": "Dirty Plastic Bag",
+ "item.paperClip": "Paper Clip",
+ "item.toothpick": "Toothpick",
+ "item.foodPackagingBag": "Food Packaging Bag",
+ "item.watercolorPen": "Watercolor Pen",
+ "item.cottonSwab": "Cotton Swab"
+}
diff --git a/config/i18n/ja.json b/config/i18n/ja.json
new file mode 100644
index 0000000..558beaa
--- /dev/null
+++ b/config/i18n/ja.json
@@ -0,0 +1,305 @@
+{
+ "page.title": "涓婃捣甯傘偞銉熷垎鍒ャ偓銈ゃ儔",
+ "header.title": "涓婃捣甯傘伄鐢熸椿銈淬儫銇仼銇嗗垎鍒ャ仚銈嬶紵",
+ "btn.home": "銉涖兗銉�",
+ "btn.query": "妞滅储",
+ "btn.voice": "闀锋娂銇楅煶澹�",
+ "btn.standard": "鎺掑嚭鍩烘簴",
+ "btn.home.short": "銉涖兗銉�",
+ "search.placeholder": "銈淬儫銇悕鍓嶃倰鍏ュ姏",
+ "search.notFoundHint": "銇婃帰銇椼伄闋呯洰銇岃銇ゃ亱銈娿伨銇涖倱銇с仐銇熴�備互涓嬨伅銇勩亱銇屻仹銇欍亱锛�",
+ "search.referenceHint": "浠ヤ笅銇垎椤炴儏鍫便倰銇斿弬鐓с亸銇犮仌銇勩��",
+ "search.noResults": "闁㈤�c仚銈嬮爡鐩亴瑕嬨仱銇嬨倞銇俱仜銈撱�傚垾銇偔銉笺儻銉笺儔銈掋亰瑭︺仐銇忋仩銇曘亜銆�",
+ "lang.zh": "涓浗瑾�",
+ "lang.en": "鑻辫獮",
+ "lang.ko": "闊撳浗瑾�",
+ "footer.copyright": "涓婃捣浜敵 Copyright 漏 2026",
+ "welcome.title": "銇旀鍐�",
+ "welcome.p1": "1. 銈淬儫銇寮忋仾涓浗瑾炲悕绉帮紙鏉愯唱銈掑惈銈�锛夈倰鍏ュ姏銇椼仸銇忋仩銇曘亜銆備緥锛氥偓銉┿偣鐡躲�佷娇銇勬崹銇︺儣銉┿偣銉併儍銈偒銉冦儣銆侀櫠鍣ㄣ伄纰椼仾銇┿��",
+ "welcome.p2": "2. 鐢熸椿銈淬儫鍒嗛銇叿浣撶殑鍩烘簴銇�佺祵娓堢ぞ浼氱櫤灞曟按婧栥�佺敓娲汇偞銉熴伄鐗规�с�佸嚘鐞嗐兓鍒╃敤鏂规硶銇熀銇ャ亜銇︾窗鍒嗗寲銉昏鏁淬仌銈屻伨銇欍��",
+ "welcome.p3": "3. 鏈绱€偡銈广儐銉犮伅鍙傝�冪敤銇с仚銆傚叿浣撶殑銇垎椤炶浠躲伅绠¤絼銇皞闁�绠$悊閮ㄩ杸銇熀婧栥伀寰撱仯銇︺亸銇犮仌銇勩��",
+ "welcome.confirm": "浜嗚В",
+ "disposal.suggestLabel": "鎺掑嚭鍏堬細",
+ "disposal.tipsTitle": "璞嗙煡璀�",
+ "cat.recyclable": "璩囨簮銇斻伩",
+ "cat.recyclable.desc": "寤冪礄銆佸粌銉椼儵銈广儊銉冦偗銆佸粌銈儵銈硅=鍝併�佸粌閲戝睘銆佸粌绻婄董銇仼銆併儶銈点偆銈儷銉诲啀鍒╃敤銇仼銇椼仧鐢熸椿寤冩鐗┿倰鎸囥仐銇俱仚銆�",
+ "cat.recyclable.standard": "1. 杌姐亸鍏ャ倢銇︺亸銇犮仌銇勩�俓n2. 娓呮綌銇т咕鐕ャ仐銇熺姸鎱嬨倰淇濄仭銆佹睔鏌撱倰閬裤亼銇︺亸銇犮仌銇勩�俓n3. 绱欓銇仹銇嶃倠銇犮亼骞炽倝銇�佷咕鐕ャ仌銇涖仸銇忋仩銇曘亜銆俓n4. 銉椼儵銈广儊銉冦偗椤炪伅娈嬬疆鐗┿倰鍙栥倞闄ゃ亶銆佹礂銇c仸涔俱亱銇椼仸銇忋仩銇曘亜銆俓n5. 绔嬩綋鍖呰銇腑韬倰绌恒伀銇椼�佹竻鎺冨緦銇桨銇椼仸鎺掑嚭銇椼仸銇忋仩銇曘亜銆俓n6. 閶亜瑙掋亴銇傘倠銈傘伄銇寘銈撱仹鎺掑嚭銇椼仸銇忋仩銇曘亜銆俓n7. 閲戝睘椤炪伅娈嬬疆鐗┿倰鍙栥倞闄ゃ亶銆佹桨銇椼仸鎺掑嚭銇椼仸銇忋仩銇曘亜銆俓n8. 绻婄董椤炪伅娲椼仯銇︿咕銇嬨仐銆併仧銇熴倱銇ф帓鍑恒仐銇︺亸銇犮仌銇勩��",
+ "cat.hazardous": "鏈夊銇斻伩",
+ "cat.hazardous.desc": "浜轰綋銇仴搴枫倓鑷劧鐠板銇洿鎺ョ殑銇俱仧銇綔鍦ㄧ殑銇嵄瀹炽倰鍙娿伡銇欑敓娲诲粌妫勭墿銆傚粌闆绘睜銆佸粌鐏銆佸粌钖搧銆佸粌銉氥兂銈仺銇濄伄瀹瑰櫒銇仼銇屽惈銇俱倢銇俱仚銆�",
+ "cat.hazardous.standard": "1. 鏈夊銇斻伩銇唤銇忓叆銈屻�佸銈屻倓銇欍亜銈傘伄銇寘銈撱仹鎺掑嚭銇椼仸銇忋仩銇曘亜銆俓n2. 寤冮浕姹犮伅鍒嗚В銇涖仛銆佸畬鍏ㄣ仾鐘舵厠銈掍繚銇c仸銇忋仩銇曘亜銆俓n3. 寤冪伅绠°伅鍓层倢銇亜銈堛亞绱欍仹鍖呫倱銇ф帓鍑恒仐銇︺亸銇犮仌銇勩�俓n4. 寤冭柆鍝併伅鍖呰銇ㄤ竴绶掋伀鎺掑嚭銇椼仸銇忋仩銇曘亜銆俓n5. 寤冦儦銉炽偔缂躲伅瀵嗗皝銇椼仸銇忋仩銇曘亜銆俓n6. 瀹夊叏銇敞鎰忋仐銆佹紡銈屻倰閬裤亼銇︺亸銇犮仌銇勩�俓n7. 鎻櫤鎬с伄銈傘伄銇瘑灏併仐銇︽帓鍑恒仐銇︺亸銇犮仌銇勩��",
+ "cat.wet": "婀裤仯銇熴仈銇�",
+ "cat.wet.desc": "鑵愩倞銈勩仚銇勭敓娲荤墿璩兓鐢熸椿寤冩鐗┿�傞鏉愩亸銇氥�佹畫銈婄墿銆佹湡闄愬垏銈岄鍝併�佹灉鐗┿伄鐨兓鏍搞�佽姳銆佹饥鏂硅柆銇亱銇欍仾銇┿亴鍚伨銈屻伨銇欍��",
+ "cat.wet.standard": "1. 姘村垏銈娿仐銇︺亱銈夋帓鍑恒仐銇︺亸銇犮仌銇勩�俓n2. 绱旂矉銇恫浣撱伅鎺掓按鍙c伀娴併仐銇︺亸銇犮仌銇勩�俓n3. 鍖呰銇屻亗銈嬫箍銇c仧銇斻伩銇寘瑁呫倰澶栥仐銇︺亸銇犮仌銇勩�俓n4. 澶с亶銇銆佽矟娈婚銇咕銇勩仧銇斻伩銇ㄣ仐銇︽帓鍑恒仐銇︺亸銇犮仌銇勩�俓n5. 鍘ㄤ綑銇斻伩銇暟鐗┿倰鍙栥倞闄ゃ亜銇︽帓鍑恒仐銇︺亸銇犮仌銇勩��",
+ "cat.dry": "涔俱亜銇熴仈銇�",
+ "cat.dry.desc": "璩囨簮銇斻伩銆佹湁瀹炽仈銇裤�佹箍銇c仧銇斻伩浠ュ銇仢銇粬銇敓娲诲粌妫勭墿銆�",
+ "cat.dry.standard": "1. 銇с亶銈嬨仩銇戞按鍒囥倞銇椼仸銇忋仩銇曘亜銆俓n2. 鍒嗛銇岄洠銇椼亜鐢熸椿銇斻伩銇咕銇勩仧銇斻伩瀹瑰櫒銇叆銈屻仸銇忋仩銇曘亜銆俓n3. 浣撶銇ぇ銇嶃亜銇斻伩銇仼鍒囥伀鍒嗚В銇椼仸銇忋仩銇曘亜銆俓n4. 浣裤亜鎹ㄣ仸椋熷櫒銆併儐銈c儍銈枫儱銇咕銇勩仧銇斻伩銇с仚銆俓n5. 鍚搞亜娈汇伅瀹屽叏銇秷銇椼仸銇嬨倝鎺掑嚭銇椼仸銇忋仩銇曘亜銆�",
+ "disposal.suggest.recyclable": "璩囨簮銇斻伩",
+ "disposal.line1.recyclable": "娓呮綌銇т咕鐕ャ仐銇熺姸鎱嬨倰淇濄仭銆佹睔鏌撱倰閬裤亼銇︺亸銇犮仌銇勩��",
+ "disposal.line2.recyclable": "鎺掑嚭鍓嶃伀娈嬬疆鐗┿倰鍙栥倞闄ゃ亶銆佹桨銇椼仸瀹圭銈掓笡銈夈仐銇︺亸銇犮仌銇勩��",
+ "disposal.tip1.recyclable": "璩囨簮銇斻伩銇儶銈点偆銈儷鍑︾悊銇倛銈婃柊銇椼亜瑁藉搧銇啀鐢熴仌銈屻�佽硣婧愩倰绡�绱勩仐銇俱仚銆�",
+ "disposal.tip2.recyclable": "銉椼儵銈广儊銉冦偗銉溿儓銉�1鏈伄銉偟銈ゃ偗銉仹60W闆荤悆銈�3鏅傞枔鐐圭伅銇с亶銈嬮浕鍔涖倰绡�绱勩仹銇嶃伨銇欍��",
+ "disposal.tip3.recyclable": "绱�1銉堛兂銇儶銈点偆銈儷銇�17鏈伄鏈ㄣ倰绡�绱勩仹銇嶃伨銇欍��",
+ "disposal.tip4.recyclable": "銈淬儫鍒嗗垾銇皬銇曘仾瀹熻返銇嬨倝銆傝硣婧愩伄寰挵鍒╃敤銇仱銇亽銇俱仐銈囥亞銆�",
+ "disposal.suggest.hazardous": "鏈夊銇斻伩",
+ "disposal.line1.hazardous": "杌姐亸鍏ャ倢銆佸銈屻倓銇欍亜銈傘伄銇寘銈撱仹鎺掑嚭銇椼仸銇忋仩銇曘亜銆�",
+ "disposal.line2.hazardous": "寤冮浕姹犮�佸粌鐏銇仼銇垎瑙c仜銇氥�佸畬鍏ㄣ仾鐘舵厠銈掍繚銇c仸銇忋仩銇曘亜銆�",
+ "disposal.tip1.hazardous": "鏈夊銇斻伩銇伅鍋ュ悍銈勭挵澧冦伀鏈夊銇墿璩亴鍚伨銈屻�佺壒鍒ャ仾鍑︾悊銇屽繀瑕併仹銇欍��",
+ "disposal.tip2.hazardous": "寤冮浕姹�1鍊嬨倰鐒¢�犱綔銇崹銇︺倠銇�1銕°伄鍦熷湴銈�50骞撮枔姹氭煋銇欍倠鍙兘鎬с亴銇傘倞銇俱仚銆�",
+ "disposal.tip3.hazardous": "寤冭泹鍏夌伅绠°伀銇按閵�銇屽惈銇俱倢銆佸壊銈屻倠銇ㄧ┖姘椼仺鍦熷銈掓睔鏌撱仐銇俱仚銆�",
+ "disposal.tip4.hazardous": "鏈夊銇斻伩銈掓銇椼亸鎺掑嚭銇欍倠銇撱仺銇с�佸仴搴枫仺鐠板銈掑畧銈娿伨銇欍��",
+ "disposal.suggest.wet": "婀裤仯銇熴仈銇�",
+ "disposal.line1.wet": "姘村垏銈娿仐銇︺亱銈夋帓鍑恒仐銆佺磾绮嬨仾娑蹭綋銇帓姘村彛銇祦銇椼仸銇忋仩銇曘亜銆�",
+ "disposal.line2.wet": "鍖呰銇屻亗銈嬫箍銇c仧銇斻伩銇寘瑁呫倰澶栥仐銇︺亱銈夊垎鍒ャ仐銇︺亸銇犮仌銇勩��",
+ "disposal.tip1.wet": "婀裤仯銇熴仈銇裤伅鐢熷寲瀛﹀嚘鐞嗐伀銈堛倞鏈夋鑲ユ枡銇虎鎻涖仹銇嶃伨銇欍��",
+ "disposal.tip2.wet": "涓婃捣銇с伅姣庢棩绱�1涓囥儓銉炽伄婀裤仯銇熴仈銇裤亴鐧虹敓銇椼伨銇欍�傛銇椼亜鍒嗗垾銇岄噸瑕併仹銇欍��",
+ "disposal.tip3.wet": "鎺掑嚭鍓嶃伀姘村垏銈娿倰鍗佸垎銇銇嗐仺銆佹蹈鍑烘恫銇櫤鐢熴倰娓涖倝銇涖伨銇欍��",
+ "disposal.tip4.wet": "娈嬨倞鐗┿倐璩囨簮寰挵銇泊閲嶃仾鏉愭枡銇仾銈娿伨銇欍��",
+ "disposal.suggest.dry": "涔俱亜銇熴仈銇�",
+ "disposal.line1.dry": "銇с亶銈嬨仩銇戞按鍒囥倞銇椼仸銇嬨倝鎺掑嚭銇椼仸銇忋仩銇曘亜銆�",
+ "disposal.line2.dry": "鍒嗛銇岄洠銇椼亜鐢熸椿銇斻伩銇咕銇勩仧銇斻伩銇叆銈屻仸銇忋仩銇曘亜銆�",
+ "disposal.tip1.dry": "涔俱亜銇熴仈銇裤伅涓汇伀鐒煎嵈銇俱仧銇煁绔嬨仹鍑︾悊銇曘倢銇俱仚銆�",
+ "disposal.tip2.dry": "涔俱亜銇熴仈銇裤倰娓涖倝銇欍伀銇�佸垎鍒ャ倰鐢熸椿鍖栥仚銈嬨亾銇ㄣ亴閲嶈銇с仚銆�",
+ "disposal.tip3.dry": "銉嗐偅銉冦偡銉ャ�佸惛銇勬銆佷娇銇勬崹銇﹂鍣ㄣ仾銇┿伅涔俱亜銇熴仈銇裤仹銇欍��",
+ "disposal.tip4.dry": "銈淬儫鍒嗗垾銇с�併倛銈婄編銇椼亜閮藉競銈掍綔銈娿伨銇椼倗銇嗐��",
+ "lang.ja": "鏃ユ湰瑾�",
+ "item.milkBox": "鐗涗钩銉戙儍銈�",
+ "item.plastic": "銉椼儵銈广儊銉冦偗",
+ "item.glassBottle": "銈儵銈圭摱",
+ "item.glass": "銈儵銈�",
+ "item.paper": "绱�",
+ "item.clothes": "琛i",
+ "item.brokenGlass": "鍓层倢銇熴偓銉┿偣",
+ "item.can": "銈€儷銉熺级",
+ "item.plasticBox": "銉椼儵銈广儊銉冦偗绠�",
+ "item.foamBoard": "鐧烘场銉溿兗銉�",
+ "item.powerBank": "銉€儛銈ゃ儷銉愩儍銉嗐儶銉�",
+ "item.shoes": "闈�",
+ "item.paperBox": "绱欑",
+ "item.foamBox": "鐧烘场銈广儊銉兗銉",
+ "item.glassCup": "銈儵銈广偝銉冦儣",
+ "item.newspaper": "鏂拌仦绱�",
+ "item.plasticCup": "銉椼儵銈广儊銉冦偗銈儍銉�",
+ "item.wire": "闆荤窔",
+ "item.dataCable": "銉囥兗銈裤偙銉笺儢銉�",
+ "item.waterBottle": "銉熴儘銉┿儷銈︺偐銉笺偪銉笺儨銉堛儷",
+ "item.pillow": "鏋�",
+ "item.blade": "鍒冪墿",
+ "item.screw": "銉嶃偢",
+ "item.foamPlastic": "鐧烘场銉椼儵銈广儊銉冦偗",
+ "item.yogurtTetraPak": "銉ㄣ兗銈般儷銉堛儐銉堛儵銉戙儍銈�",
+ "item.paperBag": "绱欒",
+ "item.cosmeticPlasticBottle": "鍖栫钵鍝併儣銉┿偣銉併儍銈┖鐡�",
+ "item.leatherShoes": "闈╅澊",
+ "item.cosmeticGlassBottle": "鍖栫钵鍝併偓銉┿偣绌虹摱",
+ "item.wineBottle": "閰掔摱",
+ "item.chargingCable": "鍏呴浕銈便兗銉栥儷",
+ "item.flyer": "銉併儵銈�",
+ "item.wastePlastic": "寤冦儣銉┿偣銉併儍銈�",
+ "item.cigaretteBox": "銈裤儛銈炽伄绠�",
+ "item.charger": "鍏呴浕鍣�",
+ "item.book": "鏇哥睄",
+ "item.beerBottle": "銉撱兗銉摱",
+ "item.cardboardBox": "娈点儨銉笺儷绠�",
+ "item.woodChopsticks": "鏈ㄨ=绠�",
+ "item.plushToy": "銇亜銇愩倠銇�",
+ "item.bedSheet": "銈枫兗銉�",
+ "item.scissors": "銇仌銇�",
+ "item.drinkPlasticBottle": "椋叉枡銉椼儵銈广儊銉冦偗銉溿儓銉�",
+ "item.fabric": "甯�",
+ "item.dehumidifierBox": "闄ゆ箍鍓ゃ儨銉冦偗銈�",
+ "item.magnet": "纾佺煶",
+ "item.plasticWrap": "銉椼儵銈广儊銉冦偗鍖呰绱�",
+ "item.quilt": "甯冨洠",
+ "item.tetraPak": "銉嗐儓銉┿儜銉冦偗",
+ "item.basketball": "銉愩偣銈便儍銉堛儨銉笺儷",
+ "item.aluminumFoil": "銈€儷銉熴儧銈ゃ儷",
+ "item.socket": "銈炽兂銈汇兂銉�",
+ "item.iron": "閴�",
+ "item.key": "閸�",
+ "item.printingPaper": "鍗板埛鐢ㄧ礄",
+ "item.metal": "閲戝睘",
+ "item.whitePaper": "鐧界礄",
+ "item.packagingBox": "鍖呰绱欑",
+ "item.plasticLid": "銉椼儵銈广儊銉冦偗钃�",
+ "item.envelope": "灏佺瓛",
+ "item.medicinePackaging": "钖伄鍖呰",
+ "item.medicineBottle": "钖摱",
+ "item.lightBulb": "闆荤悆",
+ "item.paintBucket": "銉氥兂銈级",
+ "item.medicine": "钖搧",
+ "item.expiredMedicine": "鏈熼檺鍒囥倢銇柆",
+ "item.rechargeableBattery": "鍏呴浕寮忛浕姹�",
+ "item.nailPolish": "銉炪儖銈儱銈�",
+ "item.storageBattery": "钃勯浕姹�",
+ "item.emptyMedicineBottle": "绌恒伄钖摱",
+ "item.hazardousWaste": "鏈夊銇斻伩",
+ "item.expiredMedicine2": "鏈熼檺鍒囥倢鍖昏柆鍝�",
+ "item.wasteMedicine": "寤冭柆鍝�",
+ "item.lightTube": "铔嶅厜鐏",
+ "item.fluorescentTube": "铔嶅厜绠�",
+ "item.niCdBattery": "銉嬨儍銈便儷銈儔銉熴偊銉犻浕姹�",
+ "item.photo": "鍐欑湡",
+ "item.fluorescentLamp": "铔嶅厜鐏�",
+ "item.hairDyeShell": "銉樸偄銈儵銉煎鍣�",
+ "item.eyeDrops": "鐩柆",
+ "item.energySavingLamp": "鐪併偍銉嶃儵銉炽儣",
+ "item.insecticide": "娈鸿櫕鍓�",
+ "item.medicineTablet": "閷犲墹",
+ "item.medicineTabletBox": "閷犲墹銇",
+ "item.oralLiquidBottle": "鍐呮湇娑茶柆鐡�",
+ "item.wasteMedicineBottle": "寤冭柆鐡�",
+ "item.paint": "銉氥兂銈�",
+ "item.buttonBattery": "銉溿偪銉抽浕姹�",
+ "item.contraceptive": "閬垮钖�",
+ "item.eyeDropsBottle": "鐩柆鐡�",
+ "item.film": "銉曘偅銉儬",
+ "item.capsule": "銈儣銈汇儷",
+ "item.mercuryThermometer": "姘撮妧浣撴俯瑷�",
+ "item.ratPoison": "銉嶃偤銉熻柆",
+ "item.capsuleBlister": "銈儣銈汇儷銉婚尃鍓ゃ偡銉笺儓",
+ "item.hairDyeCan": "銉樸偄銈儵銉肩级",
+ "item.energySavingBulb": "鐪併偍銉嶉浕鐞�",
+ "item.allExpiredMedicine": "鍚勭ó鏈熼檺鍒囥倢鍖昏柆鍝�",
+ "item.incandescentBulb": "鐧界啽闆荤悆",
+ "item.phoneBattery": "鎼哄腐闆昏┍銉愩儍銉嗐儶銉�",
+ "item.disinfectantBottle": "娑堟瘨娑茬摱",
+ "item.expiredTablets": "鏈熼檺鍒囥倢閷犲墹",
+ "item.coldMedicine": "棰ㄩ偑钖�",
+ "item.disinfectant84Bottle": "84娑堟瘨娑茬┖鐡�",
+ "item.nailPolishBottle": "銉炪儖銈儱銈㈢摱",
+ "item.sprayCan": "娈鸿櫕銈广儣銉兗缂�",
+ "item.photoNegative": "鍐欑湡銉曘偅銉儬",
+ "item.chinesePatentMedicine": "涓垚钖�",
+ "item.filmRoll": "銉曘偅銉儬銉兗銉�",
+ "item.medicineShell": "钖伄鍖呰娈�",
+ "item.mercury": "姘撮妧",
+ "item.photo2": "鍐欑湡",
+ "item.wastePaintBucket": "寤冦儦銉炽偔缂�",
+ "item.expiredDrug": "鏈熼檺鍒囥倢钖墿",
+ "item.medicineBlister": "钖伄銈€儷銉熴儣銉┿偣銉併儍銈澘",
+ "item.cockroachMedicine": "銈淬偔銉栥儶钖�",
+ "item.cockroachBall": "銈淬偔銉栥儶涓�",
+ "item.capsuleTablet": "銈儣銈汇儷銉婚尃鍓�",
+ "item.disinfectantTablet": "娑堟瘨閷�",
+ "item.energySavingTube": "鐪併偍銉嶈泹鍏夌",
+ "item.melonSeedShell": "鐡滃瓙銇",
+ "item.eggShell": "鍗点伄娈�",
+ "item.cornCob": "銇ㄣ亞銈傘倣銇撱仐銇姱",
+ "item.eggshell": "鍗垫",
+ "item.corn": "銇ㄣ亞銈傘倣銇撱仐",
+ "item.walnut": "銈儷銉�",
+ "item.peanutShell": "銉斻兗銉娿儍銉勩伄娈�",
+ "item.tea": "鑼惰憠",
+ "item.lobsterShell": "銉儢銈广偪銉笺伄娈�",
+ "item.crayfish": "銈躲儶銈儖",
+ "item.crabShell": "銈儖銇",
+ "item.chickenBone": "槎忋伄楠�",
+ "item.melonSeed": "鐡滃瓙",
+ "item.crabShell2": "銈儖銇",
+ "item.cookedCornCob": "鑼广仹銇熴仺銇嗐倐銈嶃亾銇椼伄鑺�",
+ "item.pistachioShell": "銉斻偣銈裤儊銈伄娈�",
+ "item.crayfishShell": "銈躲儶銈儖銇",
+ "item.edamameShell": "鏋濊眴銇",
+ "item.shrimpShell": "銈ㄣ儞銇",
+ "item.bananaPeel": "銉愩儕銉娿伄鐨�",
+ "item.watermelonRind": "銈广偆銈伄鐨�",
+ "item.chestnutShell": "鏍椼伄娈�",
+ "item.fishBone": "榄氥伄楠�",
+ "item.lobster": "銉儢銈广偪銉�",
+ "item.cornCore": "銇ㄣ亞銈傘倣銇撱仐鑺�",
+ "item.melonSeedPiece": "鐡滃瓙銇牬鐗�",
+ "item.flower": "鑺�",
+ "item.coffeeGrounds": "銈炽兗銉掋兗銇嬨仚",
+ "item.porkRibs": "銈广儦銈€儶銉�",
+ "item.zongzi": "銇°伨銇�",
+ "item.herbalDregs": "婕㈡柟钖伄銇嬨仚",
+ "item.egg": "鍗�",
+ "item.crab": "銈儖",
+ "item.lycheeShell": "銉┿偆銉併伄娈�",
+ "item.peach": "妗�",
+ "item.plumPit": "姊呭共銇椼伄鏍�",
+ "item.jujubePit": "銉娿儎銉°伄鏍�",
+ "item.chickenBone2": "槎忛",
+ "item.expiredFood": "鏈熼檺鍒囥倢椋熷搧",
+ "item.fishBone2": "榄氶",
+ "item.apple": "銈娿倱銇�",
+ "item.lycheePit": "銉┿偆銉併伄鏍�",
+ "item.bayberry": "銉ゃ優銉€儮",
+ "item.watermelonSeed": "銈广偆銈伄绋�",
+ "item.chestnutShell2": "鏍椼伄娈�",
+ "item.cockroach2": "銈淬偔銉栥儶",
+ "item.fruitPeel": "鏋滅墿銇毊",
+ "item.mangoPit": "銉炪兂銈淬兗銇牳",
+ "item.peanut": "銉斻兗銉娿儍銉�",
+ "item.driedPeanutShell": "骞层仐銇熴償銉笺儕銉冦儎銇",
+ "item.biscuit": "銉撱偣銈便儍銉�",
+ "item.watermelon": "銈广偆銈�",
+ "item.freshFlower": "鐢熻姳",
+ "item.redJujubePit": "璧ゃ儕銉勩儭銇牳",
+ "item.lusuji": "鑺︾ǚ",
+ "item.appleCore": "銈娿倱銇斻伄鑺�",
+ "item.waterBambooPeel": "銈躲兗銈点偆銇毊",
+ "item.bread": "銉戙兂",
+ "item.banana": "銉愩儕銉�",
+ "item.teaResidue": "鑼惰憠銇嬨仚",
+ "item.plasticBag": "銉撱儖銉笺儷琚�",
+ "item.zongziLeaf": "銇°伨銇嶃伄钁�",
+ "item.walnutShell": "銈儷銉熴伄娈�",
+ "item.hair": "楂伄姣�",
+ "item.shell": "璨濇",
+ "item.sanitaryPad": "鐢熺悊鐢ㄣ儕銉椼偔銉�",
+ "item.condom": "銈炽兂銉夈兗銉�",
+ "item.chewingGum": "銈儬",
+ "item.lighter": "銉┿偆銈裤兗",
+ "item.coconutShell": "銈炽偝銉娿儍銉勩伄娈�",
+ "item.catLitter": "鐚爞",
+ "item.faceMask": "銉曘偋銈ゃ偣銉炪偣銈�",
+ "item.tissue": "銉娿儣銈兂",
+ "item.bigBone": "澶с亶銇",
+ "item.milkTeaCup": "銈裤償銈偒銉嗐偅銉笺偒銉冦儣",
+ "item.paperTowel": "銉嗐偅銉冦偡銉�",
+ "item.clamShell": "銈€偟銉伄娈�",
+ "item.zongziLeaf2": "銇°伨銇嶃伄钁�",
+ "item.cornHusk": "銇ㄣ亞銈傘倣銇撱仐銇毊",
+ "item.straw": "銈广儓銉兗",
+ "item.teaBag": "銉嗐偅銉笺儛銉冦偘",
+ "item.sugarcanePeel": "銈点儓銈︺偔銉撱伄鐨�",
+ "item.desiccant": "涔剧嚗鍓�",
+ "item.disposableChopsticks": "浣裤亜鎹ㄣ仸绠�",
+ "item.cornShell": "銇ㄣ亞銈傘倣銇撱仐銇",
+ "item.cigarette": "鍚搞亜娈�",
+ "item.wetWipe": "銈︺偋銉冦儓銉嗐偅銉冦偡銉�",
+ "item.durianShell": "銉夈儶銈€兂銇",
+ "item.toiletPaper": "銉堛偆銉儍銉堛儦銉笺儜銉�",
+ "item.bigWalnutShell": "澶с亶銇偗銉儫銇",
+ "item.nail": "鐖�",
+ "item.packagingBag": "鍖呰琚�",
+ "item.lipstick": "鍙g磪",
+ "item.disposableCup": "浣裤亜鎹ㄣ仸銈儍銉�",
+ "item.snailShell": "宸汇亶璨濄伄娈�",
+ "item.toothbrush": "姝儢銉┿偡",
+ "item.takeoutBox": "銉嗐偆銈偄銈︺儓瀹瑰櫒",
+ "item.durian": "銉夈儶銈€兂",
+ "item.diaper": "銇娿個銇�",
+ "item.trashBag": "銈淬儫琚�",
+ "item.toothpasteTube": "姝(銇嶃儊銉ャ兗銉�",
+ "item.icePack": "淇濆喎鍓�",
+ "item.sock": "闈翠笅",
+ "item.pen": "銉氥兂",
+ "item.diaper2": "绱欍亰銈�銇�",
+ "item.durianPit": "銉夈儶銈€兂銇ó",
+ "item.disposableLunchBox": "浣裤亜鎹ㄣ仸寮佸綋绠�",
+ "item.teaBag2": "鑼惰憠銉戙儍銈�",
+ "item.mask": "銉炪偣銈�",
+ "item.underwear": "涓嬬潃",
+ "item.towel": "銈裤偑銉�",
+ "item.diaper3": "銇娿個銇�",
+ "item.ceramicBowl": "闄跺櫒銇",
+ "item.penRefill": "銉氥兂鑺�",
+ "item.dirtyPlasticBag": "姹氥倢銇熴儞銉嬨兗銉",
+ "item.paperClip": "銈儶銉冦儣",
+ "item.toothpick": "鐖鏋�",
+ "item.foodPackagingBag": "椋熷搧鍖呰琚�",
+ "item.watercolorPen": "姘村僵銉氥兂",
+ "item.cottonSwab": "缍挎"
+}
diff --git a/config/i18n/ko.json b/config/i18n/ko.json
new file mode 100644
index 0000000..1e84eec
--- /dev/null
+++ b/config/i18n/ko.json
@@ -0,0 +1,305 @@
+{
+ "page.title": "靸來晿鞚� 鞊半爤旮� 攵勲 臁绊殞",
+ "header.title": "靸來晿鞚� 靸濏櫆 鞊半爤旮�, 鞏措柣瓴� 攵勲頃犼箤鞖�?",
+ "btn.home": "頇�",
+ "btn.query": "臁绊殞",
+ "btn.voice": "旮戈矊 雸岆煬 鞚岇劚",
+ "btn.standard": "氚办稖 旮办",
+ "btn.home.short": "頇�",
+ "search.placeholder": "鞊半爤旮� 鞚措 鞛呺牓",
+ "search.notFoundHint": "鞗愴晿鞁滊姅 頃鞚� 彀眷 氇豁枅鞀惦媹雼�. 鞎勲灅 頃鞚� 鞏措枲靹胳殧?",
+ "search.referenceHint": "鞎勲灅 攵勲 鞝曤炒毳� 彀戈碃頃� 欤检劯鞖�.",
+ "search.noResults": "甏�霠� 頃鞚� 彀眷潉 靾� 鞐嗢姷雼堧嫟. 雼るジ 韨れ泴霌滊ゼ 鞁滊弰頃� 氤挫劯鞖�.",
+ "lang.zh": "欷戧淡鞏�",
+ "lang.en": "鞓侅柎",
+ "lang.ko": "頃滉淡鞏�",
+ "footer.copyright": "靸來晿鞚� 歆曥厴 Copyright 漏 2026",
+ "welcome.title": "鞎堧偞 毵愳攢",
+ "welcome.p1": "1. 鞊半爤旮办潣 鞝曥儊鞝侅澑 欷戧淡鞏� 鞚措(鞛 韽暔)鞚� 鞛呺牓頃橃劯鞖�. 鞓�: 鞙犽Μ氤�, 鞚柬殞鞖� 頂岆澕鞀ろ嫳 旎�, 霃勳瀽旮� 攴鸽 霌�.",
+ "welcome.p2": "2. 靸濏櫆 鞊半爤旮� 攵勲鞚� 甑泊鞝侅澑 旮办鞚� 瓴届牅路靷殞 氚滌爠 靾橃, 靸濏櫆 鞊半爤旮� 韸轨劚 氚� 觳橂Μ路鞚挫毄 氚╇矔鞐� 霐半澕 靹鸽秳頇斅缝“鞝曤惄雼堧嫟.",
+ "welcome.p3": "3. 氤� 臁绊殞 鞁滌姢韰滌潃 彀戈碃鞖╈澊氅�, 甑泊鞝侅澑 攵勲 鞖旉贝鞚� 甏�頃� 鞝勲 甏�毽� 攵�靹� 旮办鞚� 霐半雼堧嫟.",
+ "welcome.confirm": "鞎岅矤鞀惦媹雼�",
+ "disposal.suggestLabel": "氚办稖 甓岇灔:",
+ "disposal.tipsTitle": "鞎岇晞霊愳劯鞖�",
+ "cat.recyclable": "鞛櫆鞖╉拡",
+ "cat.recyclable.desc": "韽愳, 韽愴攲霛检姢韹�, 韽愳湢毽� 鞝滍拡, 韽愱笀靻�, 韽愳氍� 霌� 鞛櫆鞖� 氚� 靾滍櫂 鞚挫毄鞚� 臧�電ロ暅 靸濏櫆 韽愱赴氍检潉 毵愴暕雼堧嫟.",
+ "cat.recyclable.standard": "1. 臧�氤嶊矊 雱l溂靹胳殧.\n2. 旯仐頃橁碃 瓯挫“頃橁矊, 鞓れ椉鞚� 頂柬晿靹胳殧.\n3. 膦呾澊電� 韽夗弶頃橁矊, 瓯挫“頃橁矊 鞙犾頃橃劯鞖�.\n4. 頂岆澕鞀ろ嫳鞚� 鞛旍棳氍检潉 鞝滉卑頃橁碃 項龟惮鞏� 毵愲Μ靹胳殧.\n5. 鞛呾泊 韽灔鞚� 雮挫毄氍检潉 牍勳毎瓿� 觳唽 頉� 雸岆煬靹� 氚办稖頃橃劯鞖�.\n6. 雮犾勾搿滌毚 氇劀毽姅 臧愳嫺靹� 氚办稖頃橃劯鞖�.\n7. 旮堨啀鞚� 鞛旍棳氍检潉 鞝滉卑頃橁碃 雸岆煬靹� 氚办稖頃橃劯鞖�.\n8. 歆侂鞚� 靹疙儊 頉� 毵愲Μ瓿� 鞝戩柎靹� 氚办稖頃橃劯鞖�.",
+ "cat.hazardous": "鞙犿暣 鞊半爤旮�",
+ "cat.hazardous.desc": "鞚胳泊 瓯搓皶鞚措倶 鞛愳棸 頇橁步鞐� 歆侅爲 霕愲姅 鞛犾灛鞝� 鞙勴暣毳� 欷� 靾� 鞛堧姅 靸濏櫆 韽愱赴氍�. 韽愲鞍韯半Μ, 韽愲摫甏�, 韽愳潣鞎巾拡, 韽愴帢鞚疙姼 氚� 鞖╆赴 霌膘澊 韽暔霅╇媹雼�.",
+ "cat.hazardous.standard": "1. 鞙犿暣 鞊半爤旮半姅 臧�氤嶊矊, 旯旮� 靿毚 瓴冹潃 臧愳嫺靹� 氚办稖頃橃劯鞖�.\n2. 韽愲鞍韯半Μ電� 攵勴暣頃橃 毵愱碃 鞓爠頃橁矊 鞙犾頃橃劯鞖�.\n3. 韽愲摫甏�鞚� 旯歆� 鞎婋弰搿� 膦呾澊搿� 臧愳嫺靹胳殧.\n4. 韽愳潣鞎巾拡鞚� 韽灔瓿� 頃粯 氚办稖頃橃劯鞖�.\n5. 韽愴帢鞚疙姼 韱奠潃 氚�氪夗晿靹胳殧.\n6. 鞎堨爠鞐� 鞙犾潣頃橁碃 雸勳稖鞚� 頂柬晿靹胳殧.\n7. 頊橂皽靹� 氍检鞚� 氚�氪� 頉� 氚办稖頃橃劯鞖�.",
+ "cat.wet": "鞀奠嫕 鞊半爤旮�",
+ "cat.wet.desc": "攵�韺晿旮� 靿毚 靸濏櫆 氍检 氚� 韽愱赴氍�. 鞁濎灛耄� 彀岅杭旮�, 雮潃 鞚岇嫕, 鞙犿喌旮绊暅 歆�雮� 鞁濏拡, 瓿检澕 昊嶌路鞌�, 頇旍磮, 頃滌暯 彀岅杭旮� 霌膘澊 韽暔霅╇媹雼�.",
+ "cat.wet.standard": "1. 氍缄赴毳� 鞝滉卑頃� 頉� 氚办稖頃橃劯鞖�.\n2. 靾滌垬 鞎§泊電� 頃橃垬甑棎 氩勲Μ靹胳殧.\n3. 韽灔鞚� 鞛堧姅 鞀奠嫕 鞊半爤旮半姅 韽灔鞚� 鞝滉卑頃橃劯鞖�.\n4. 韥� 爰�, 臁瓣皽昊嶌鞚� 瓯挫嫕 鞊半爤旮半 氚办稖頃橃劯鞖�.\n5. 鞚岇嫕氍� 鞊半爤旮半姅 鞚措歆堨潉 鞝滉卑頃橃劯鞖�.",
+ "cat.dry": "瓯挫嫕 鞊半爤旮�",
+ "cat.dry.desc": "鞛櫆鞖╉拡, 鞙犿暣 鞊半爤旮�, 鞀奠嫕 鞊半爤旮� 鞕胳潣 旮绊儉 靸濏櫆 韽愱赴氍�.",
+ "cat.dry.standard": "1. 臧�電ロ晿氅� 氍缄赴毳� 鞝滉卑頃橃劯鞖�.\n2. 攵勲臧� 鞏措牑鞖� 靸濏櫆 鞊半爤旮半姅 瓯挫嫕 鞊半爤旮办棎 氚办稖頃橃劯鞖�.\n3. 攵�頂缄皜 韥� 鞊半爤旮半姅 攵勴暣頃橃劯鞖�.\n4. 鞚柬殞鞖� 鞁濌赴, 頊挫電� 瓯挫嫕 鞊半爤旮办瀰雼堧嫟.\n5. 雼措鞍杲侅磮電� 鞕勳爠頌� 雭� 頉� 氚办稖頃橃劯鞖�.",
+ "disposal.suggest.recyclable": "鞛櫆鞖╉拡",
+ "disposal.line1.recyclable": "旯仐頃橁碃 瓯挫“頃� 靸來儨搿� 鞓れ椉鞚� 頂柬暣 欤检劯鞖�.",
+ "disposal.line2.recyclable": "氚办稖 鞝� 鞛旍棳氍检潉 鞝滉卑頃橁碃 雸岆煬 攵�頂茧ゼ 欷勳棳 欤检劯鞖�.",
+ "disposal.tip1.recyclable": "鞛櫆鞖╉拡鞚� 鞛矘毽悩鞏� 靸堧鞖� 鞝滍拡鞙茧 毵岆摛鞏挫牳 鞛愳洂鞚� 鞝堨暯頃╇媹雼�.",
+ "disposal.tip2.recyclable": "頂岆澕鞀ろ嫳氤� 1臧滊ゼ 鞛櫆鞖╉晿氅� 60W 鞝勱惮毳� 3鞁滉皠 旒� 靾� 鞛堧姅 鞝勲牓鞚� 鞝堨暯頃╇媹雼�.",
+ "disposal.tip3.recyclable": "膦呾澊 1韱れ潉 鞛櫆鞖╉晿氅� 雮橂 17攴鸽(毳� 鞝堨暯頃� 靾� 鞛堨姷雼堧嫟.",
+ "disposal.tip4.recyclable": "鞛戩潃 攵勲 鞁れ矞鞚� 鞛愳洂 靾滍櫂鞐� 韥� 霃勳泙鞚� 霅╇媹雼�.",
+ "disposal.suggest.hazardous": "鞙犿暣 鞊半爤旮�",
+ "disposal.line1.hazardous": "臧�氤嶊矊 雱j碃, 旯旮� 靿毚 瓴冹潃 臧愳嫺靹� 氚办稖頃橃劯鞖�.",
+ "disposal.line2.hazardous": "韽愲鞍韯半Μ, 韽愲摫甏� 霌膘潃 攵勴暣頃橃 毵愱碃 鞓爠頃橁矊 鞙犾頃橃劯鞖�.",
+ "disposal.tip1.hazardous": "鞙犿暣 鞊半爤旮办棎電� 瓯搓皶瓿� 頇橁步鞐� 頃措鞖� 氍检鞚� 韽暔霅橃柎 韸闺硠 觳橂Μ臧� 頃勳殧頃╇媹雼�.",
+ "disposal.tip2.hazardous": "韽愲鞍韯半Μ 1臧滊ゼ 氍挫瀾鞙勲 氩勲Μ氅� 1銕� 韱犾枒鞚� 50雲勱皠 鞓れ椉鞁滍偓 靾� 鞛堨姷雼堧嫟.",
+ "disposal.tip3.hazardous": "韽愴槙甏戨摫鞐愲姅 靾橃潃鞚� 霌れ柎 鞛堨柎 旯氅� 瓿店赴鞕� 韱犾枒鞚� 鞓れ椉鞁滍偟雼堧嫟.",
+ "disposal.tip4.hazardous": "鞓皵毳� 鞙犿暣 鞊半爤旮� 氚办稖鞚� 瓯搓皶瓿� 頇橁步鞚� 氤错樃頃╇媹雼�.",
+ "disposal.suggest.wet": "鞀奠嫕 鞊半爤旮�",
+ "disposal.line1.wet": "氍缄赴毳� 鞝滉卑頃� 頉� 氚办稖頃橁碃, 靾滌垬 鞎§泊電� 頃橃垬甑棎 氩勲Μ靹胳殧.",
+ "disposal.line2.wet": "韽灔鞚� 鞛堧姅 鞀奠嫕 鞊半爤旮半姅 韽灔鞚� 鞝滉卑頃� 頉� 攵勲頃橃劯鞖�.",
+ "disposal.tip1.wet": "鞀奠嫕 鞊半爤旮半姅 靸濏檾頃� 觳橂Μ毳� 韱淀暣 鞙犼赴 牍勲搿� 鞝勴櫂霅� 靾� 鞛堨姷雼堧嫟.",
+ "disposal.tip2.wet": "靸來晿鞚措姅 頃橂( 鞎� 1毵� 韱れ潣 鞀奠嫕 鞊半爤旮半ゼ 氚办稖頃╇媹雼�. 鞓皵毳� 攵勲臧� 欷戩殧頃╇媹雼�.",
+ "disposal.tip3.wet": "氚办稖 鞝� 氍缄赴毳� 於╇秳頌� 鞝滉卑頃橂┐ 旃稖靾� 氚滌儩鞚� 欷勳澕 靾� 鞛堨姷雼堧嫟.",
+ "disposal.tip4.wet": "鞚岇嫕 彀岅杭旮半弰 鞛愳洂 靾滍櫂鞚� 靻岇頃� 鞛臧� 霅� 靾� 鞛堨姷雼堧嫟.",
+ "disposal.suggest.dry": "瓯挫嫕 鞊半爤旮�",
+ "disposal.line1.dry": "臧�電ロ晿氅� 氍缄赴毳� 鞝滉卑頃� 頉� 氚办稖頃橃劯鞖�.",
+ "disposal.line2.dry": "攵勲臧� 鞏措牑鞖� 靸濏櫆 鞊半爤旮半姅 瓯挫嫕 鞊半爤旮办棎 氚办稖頃橃劯鞖�.",
+ "disposal.tip1.dry": "瓯挫嫕 鞊半爤旮半姅 欤茧 靻岅皝 霕愲姅 毵る鞙茧 觳橂Μ霅╇媹雼�.",
+ "disposal.tip2.dry": "瓯挫嫕 鞊半爤旮半ゼ 欷勳澊霠る┐ 攵勲毳� 靸濏櫆頇旐晿電� 瓴冹澊 欷戩殧頃╇媹雼�.",
+ "disposal.tip3.dry": "頊挫, 雼措鞍杲侅磮, 鞚柬殞鞖� 鞁濌赴 霌膘潃 瓯挫嫕 鞊半爤旮办瀰雼堧嫟.",
+ "disposal.tip4.dry": "鞊半爤旮� 攵勲搿� 雿� 鞎勲雼れ毚 霃勳嫓毳� 毵岆摛鞏� 臧戩嫓雼�.",
+ "lang.ja": "鏃ユ湰瑾�",
+ "item.milkBox": "鞖办湢韺�",
+ "item.plastic": "頂岆澕鞀ろ嫳",
+ "item.glassBottle": "鞙犽Μ氤�",
+ "item.glass": "鞙犽Μ",
+ "item.paper": "膦呾澊",
+ "item.clothes": "鞓�",
+ "item.brokenGlass": "旯 鞙犽Μ",
+ "item.can": "鞎岆(氙鸽妱 旌�",
+ "item.plasticBox": "頂岆澕鞀ろ嫳 靸侅瀽",
+ "item.foamBoard": "鞀ろ嫲搿滍徏 韺�",
+ "item.powerBank": "氤挫“氚绊劙毽�",
+ "item.shoes": "鞁犽皽",
+ "item.paperBox": "膦呾澊靸侅瀽",
+ "item.foamBox": "鞀ろ嫲搿滍徏 靸侅瀽",
+ "item.glassCup": "鞙犽Μ旎�",
+ "item.newspaper": "鞁犽",
+ "item.plasticCup": "頂岆澕鞀ろ嫳 旎�",
+ "item.wire": "鞝勳劆",
+ "item.dataCable": "雿办澊韯� 旒�鞚措笖",
+ "item.waterBottle": "靸濎垬氤�",
+ "item.pillow": "氩犼皽",
+ "item.blade": "旃茧偁",
+ "item.screw": "雮橃偓",
+ "item.foamPlastic": "氚滍彫 頂岆澕鞀ろ嫳",
+ "item.yogurtTetraPak": "鞖旉惮毳错姼 韰岉姼霛柬尒",
+ "item.paperBag": "膦呾澊氪夗埇",
+ "item.cosmeticPlasticBottle": "頇旍灔頀� 頂岆澕鞀ろ嫳 牍堧硲",
+ "item.leatherShoes": "臧�欤届嫚",
+ "item.cosmeticGlassBottle": "頇旍灔頀� 鞙犽Μ 牍堧硲",
+ "item.wineBottle": "靾犽硲",
+ "item.chargingCable": "於╈爠 旒�鞚措笖",
+ "item.flyer": "甏戧碃 鞝勲嫧",
+ "item.wastePlastic": "韽愴攲霛检姢韹�",
+ "item.cigaretteBox": "雼措鞍臧�",
+ "item.charger": "於╈爠旮�",
+ "item.book": "毂�",
+ "item.beerBottle": "毵レ<氤�",
+ "item.cardboardBox": "瓿寪歆� 靸侅瀽",
+ "item.woodChopsticks": "雮橂 鞝撽皜霛�",
+ "item.plushToy": "氪夓牅 鞚疙槙",
+ "item.bedSheet": "旃寑 鞁滍姼",
+ "item.scissors": "臧�鞙�",
+ "item.drinkPlasticBottle": "鞚岆 頂岆澕鞀ろ嫳氤�",
+ "item.fabric": "觳�",
+ "item.dehumidifierBox": "鞝滌姷鞝� 靸侅瀽",
+ "item.magnet": "鞛愳劃",
+ "item.plasticWrap": "頂岆澕鞀ろ嫳 韽灔歆�",
+ "item.quilt": "鞚措秷",
+ "item.tetraPak": "韰岉姼霛柬尒",
+ "item.basketball": "雴嶊惮瓿�",
+ "item.aluminumFoil": "鞎岆(氙鸽妱 順胳澕",
+ "item.socket": "旖橃劶韸�",
+ "item.iron": "觳�",
+ "item.key": "鞐挫嚑",
+ "item.printingPaper": "鞚胳噭鞖╈",
+ "item.metal": "旮堨啀",
+ "item.whitePaper": "頋� 膦呾澊",
+ "item.packagingBox": "韽灔 膦呾澊靸侅瀽",
+ "item.plasticLid": "頂岆澕鞀ろ嫳 霘滉粦",
+ "item.envelope": "氪夗埇",
+ "item.medicinePackaging": "鞎� 韽灔",
+ "item.medicineBottle": "鞎诫硲",
+ "item.lightBulb": "鞝勱惮",
+ "item.paintBucket": "韼橃澑韸� 韱�",
+ "item.medicine": "鞎巾拡",
+ "item.expiredMedicine": "鞙犿喌旮绊暅 歆�雮� 鞎�",
+ "item.rechargeableBattery": "於╈爠 氚绊劙毽�",
+ "item.nailPolish": "毵る媹韥愳柎",
+ "item.storageBattery": "於曥爠歆�",
+ "item.emptyMedicineBottle": "牍� 鞎诫硲",
+ "item.hazardousWaste": "鞙犿暣 鞊半爤旮�",
+ "item.expiredMedicine2": "鞙犿喌旮绊暅 歆�雮� 鞚橃暯頀�",
+ "item.wasteMedicine": "韽愳潣鞎巾拡",
+ "item.lightTube": "順曣磻霌�",
+ "item.fluorescentTube": "順曣磻霌标磤",
+ "item.niCdBattery": "雼堨紙旃措摐氘� 氚绊劙毽�",
+ "item.photo": "靷",
+ "item.fluorescentLamp": "順曣磻霌�",
+ "item.hairDyeShell": "鞐检儔鞝� 鞖╆赴",
+ "item.eyeDrops": "鞎堨暯",
+ "item.energySavingLamp": "鞝堨爠霌�",
+ "item.insecticide": "靷挫订鞝�",
+ "item.medicineTablet": "鞎届爼",
+ "item.medicineTabletBox": "鞎届爼 靸侅瀽",
+ "item.oralLiquidBottle": "鞁滊熃 鞎诫硲",
+ "item.wasteMedicineBottle": "韽愳暯氤�",
+ "item.paint": "韼橃澑韸�",
+ "item.buttonBattery": "雼稊鞝勳",
+ "item.contraceptive": "頂检瀯鞎�",
+ "item.eyeDropsBottle": "鞎堨暯氤�",
+ "item.film": "頃勲",
+ "item.capsule": "旌§姁",
+ "item.mercuryThermometer": "靾橃潃 鞓弰瓿�",
+ "item.ratPoison": "欹愳暯",
+ "item.capsuleBlister": "旌§姁 鞎岇暯 韺�",
+ "item.hairDyeCan": "鞐检儔鞝� 旌�",
+ "item.energySavingBulb": "鞝堨爠 鞝勱惮",
+ "item.allExpiredMedicine": "臧侅 鞙犿喌旮绊暅 歆�雮� 鞚橃暯頀�",
+ "item.incandescentBulb": "氚膘棿鞝勱惮",
+ "item.phoneBattery": "頊措寑韽� 氚绊劙毽�",
+ "item.disinfectantBottle": "靻岆弲鞎‰硲",
+ "item.expiredTablets": "鞙犿喌旮绊暅 歆�雮� 鞎届爼",
+ "item.coldMedicine": "臧愱赴鞎�",
+ "item.disinfectant84Bottle": "84 靻岆弲鞎� 牍堧硲",
+ "item.nailPolishBottle": "毵る媹韥愳柎 氤�",
+ "item.sprayCan": "靷挫订 鞀ろ攧霠堨澊 旌�",
+ "item.photoNegative": "靷 頃勲",
+ "item.chinesePatentMedicine": "欷戩劚 頃滌暯",
+ "item.filmRoll": "頃勲 搿�",
+ "item.medicineShell": "鞎� 韽灔 昊嶋嵃旮�",
+ "item.mercury": "靾橃潃",
+ "item.photo2": "靷",
+ "item.wastePaintBucket": "韽愴帢鞚疙姼 韱�",
+ "item.expiredDrug": "鞙犿喌旮绊暅 歆�雮� 鞎诫",
+ "item.medicineBlister": "鞎� 鞎岆(氙鸽妱 韺�",
+ "item.cockroachMedicine": "氚旐�措矊霠� 鞎�",
+ "item.cockroachBall": "氚旐�措矊霠� 鞎岇暯",
+ "item.capsuleTablet": "旌§姁 鞎岇暯",
+ "item.disinfectantTablet": "靻岆弲 鞝曥牅",
+ "item.energySavingTube": "鞝堨爠 順曣磻霌标磤",
+ "item.melonSeedShell": "頃措皵霛缄赴鞌� 昊嶌",
+ "item.eggShell": "雼眬昊嶌",
+ "item.cornCob": "鞓レ垬靾橂寑",
+ "item.eggshell": "瓿勲瀫 昊嶌",
+ "item.corn": "鞓レ垬靾�",
+ "item.walnut": "順鸽憪",
+ "item.peanutShell": "霑呾僵 昊嶌",
+ "item.tea": "彀混瀻",
+ "item.lobsterShell": "霝嶌姢韯� 昊嶌",
+ "item.crayfish": "臧�鞛�",
+ "item.crabShell": "瓴� 昊嶌",
+ "item.chickenBone": "雼紙",
+ "item.melonSeed": "頃措皵霛缄赴鞌�",
+ "item.crabShell2": "瓴� 昊嶋嵃旮�",
+ "item.cookedCornCob": "鞚淀瀸 鞓レ垬靾橂寑",
+ "item.pistachioShell": "頂检姢韮�旃橃槫 昊嶌",
+ "item.crayfishShell": "臧�鞛� 昊嶌",
+ "item.edamameShell": "鞕勲憪旖� 昊嶌",
+ "item.shrimpShell": "靸堨毎 昊嶌",
+ "item.bananaPeel": "氚旊倶雮� 昊嶌",
+ "item.watermelonRind": "靾橂皶 昊嶌",
+ "item.chestnutShell": "氚� 昊嶌",
+ "item.fishBone": "靸濎劆 爰�",
+ "item.lobster": "霝嶌姢韯�",
+ "item.cornCore": "鞓レ垬靾� 鞁�",
+ "item.melonSeedPiece": "頃措皵霛缄赴鞌� 臁瓣皝",
+ "item.flower": "杲�",
+ "item.coffeeGrounds": "旎ろ敿 彀岅杭旮�",
+ "item.porkRibs": "臧堧箘",
+ "item.zongzi": "膦呾瀽",
+ "item.herbalDregs": "頃滌暯 彀岅杭旮�",
+ "item.egg": "雼眬",
+ "item.crab": "瓴�",
+ "item.lycheeShell": "毽箻 昊嶌",
+ "item.peach": "氤奠埈鞎�",
+ "item.plumPit": "頇旊Г 鞌�",
+ "item.jujubePit": "雽�於� 鞌�",
+ "item.chickenBone2": "雼紙",
+ "item.expiredFood": "鞙犿喌旮绊暅 歆�雮� 鞁濏拡",
+ "item.fishBone2": "靸濎劆 臧�鞁�",
+ "item.apple": "靷臣",
+ "item.lycheePit": "毽箻 鞌�",
+ "item.bayberry": "鞏戨Г",
+ "item.watermelonSeed": "靾橂皶鞌�",
+ "item.chestnutShell2": "氚� 昊嶌",
+ "item.cockroach2": "氚旐�措矊霠�",
+ "item.fruitPeel": "瓿检澕 昊嶌",
+ "item.mangoPit": "毵濌碃 鞌�",
+ "item.peanut": "霑呾僵",
+ "item.driedPeanutShell": "毵愲Π 霑呾僵 昊嶌",
+ "item.biscuit": "牍勳姢韨�",
+ "item.watermelon": "靾橂皶",
+ "item.freshFlower": "靸濏檾",
+ "item.redJujubePit": "雽�於� 鞌�",
+ "item.lusuji": "靾橃垬",
+ "item.appleCore": "靷臣 鞌�",
+ "item.waterBambooPeel": "甑愲氨頂�",
+ "item.bread": "牍�",
+ "item.banana": "氚旊倶雮�",
+ "item.teaResidue": "彀混瀻 彀岅杭旮�",
+ "item.plasticBag": "牍勲嫄氪夓",
+ "item.zongziLeaf": "膦呾瀽 鞛�",
+ "item.walnutShell": "順鸽憪 昊嶌",
+ "item.hair": "毹鸽Μ旃措澖",
+ "item.shell": "臁瓣皽昊嶌",
+ "item.sanitaryPad": "靸濍Μ雽�",
+ "item.condom": "旖橂彅",
+ "item.chewingGum": "昊�",
+ "item.lighter": "霛检澊韯�",
+ "item.coconutShell": "旖旍綌雱� 昊嶌",
+ "item.catLitter": "瓿犾枒鞚� 氇灅",
+ "item.faceMask": "毵堨姢韥尒",
+ "item.tissue": "雰呿偍",
+ "item.bigBone": "韥� 爰�",
+ "item.milkTeaCup": "氚�韥嫲 旎�",
+ "item.paperTowel": "頊挫",
+ "item.clamShell": "臁瓣皽 昊嶌",
+ "item.zongziLeaf2": "膦呾瀽 鞛�",
+ "item.cornHusk": "鞓レ垬靾� 昊嶌",
+ "item.straw": "牍寑",
+ "item.teaBag": "韹半氨",
+ "item.sugarcanePeel": "靷儠靾橃垬 昊嶌",
+ "item.desiccant": "瓯挫“鞝�",
+ "item.disposableChopsticks": "鞚柬殞鞖� 鞝撽皜霛�",
+ "item.cornShell": "鞓レ垬靾� 昊嶋嵃旮�",
+ "item.cigarette": "雼措鞍杲侅磮",
+ "item.wetWipe": "氍柬嫲鞀�",
+ "item.durianShell": "霊愲Μ鞎� 昊嶌",
+ "item.toiletPaper": "頇旍灔歆�",
+ "item.bigWalnutShell": "韥� 順鸽憪 昊嶌",
+ "item.nail": "靻愴啽",
+ "item.packagingBag": "韽灔氪夓",
+ "item.lipstick": "毽届姢韹�",
+ "item.disposableCup": "鞚柬殞鞖� 旎�",
+ "item.snailShell": "瓿眳鞚� 昊嶌",
+ "item.toothbrush": "旃啍",
+ "item.takeoutBox": "氚半嫭 鞖╆赴",
+ "item.durian": "霊愲Μ鞎�",
+ "item.diaper": "旮办爛攴�",
+ "item.trashBag": "鞊半爤旮半磯歆�",
+ "item.toothpasteTube": "旃橃暯 韸滊笇",
+ "item.icePack": "鞎勳澊鞀ろ尒",
+ "item.sock": "鞏戨",
+ "item.pen": "韼�",
+ "item.diaper2": "旮办爛攴�",
+ "item.durianPit": "霊愲Μ鞎� 鞌�",
+ "item.disposableLunchBox": "鞚柬殞鞖� 霃勳嫓霛巾喌",
+ "item.teaBag2": "彀混瀻 韹半氨",
+ "item.mask": "毵堨姢韥�",
+ "item.underwear": "靻嶌樂",
+ "item.towel": "靾橁贝",
+ "item.diaper3": "旮办爛攴�",
+ "item.ceramicBowl": "霃勳瀽旮� 攴鸽",
+ "item.penRefill": "韼滌嫭",
+ "item.dirtyPlasticBag": "雿旊煬鞖� 牍勲嫄氪夓",
+ "item.paperClip": "韥措",
+ "item.toothpick": "鞚挫懁鞁滉皽",
+ "item.foodPackagingBag": "鞁濏拡 韽灔氪夓",
+ "item.watercolorPen": "氍缄皭韼�",
+ "item.cottonSwab": "氅措磯"
+}
diff --git a/config/i18n/zh.json b/config/i18n/zh.json
new file mode 100644
index 0000000..624daba
--- /dev/null
+++ b/config/i18n/zh.json
@@ -0,0 +1,305 @@
+{
+ "page.title": "涓婃捣甯傚瀮鍦惧垎绫绘煡璇�",
+ "header.title": "涓婃捣甯傛棩甯哥敓娲诲瀮鍦炬�庝箞鍒嗭紵",
+ "btn.home": "棣栭〉",
+ "btn.query": "鏌ヨ",
+ "btn.voice": "闀挎寜璇煶",
+ "btn.standard": "鎶曟斁鏍囧噯",
+ "btn.home.short": "棣栭〉",
+ "search.placeholder": "杈撳叆鍨冨溇鍚嶇О",
+ "search.notFoundHint": "鎴戞壘涓嶅埌浣犳兂瑕佺殑锛岀湅鐪嬩笅闈㈣繖浜涘彲浠ュ悧锛�",
+ "search.referenceHint": "璇峰弬鑰冧互涓嬪垎绫讳俊鎭��",
+ "search.noResults": "鏈壘鍒扮浉鍏冲瀮鍦撅紝璇峰皾璇曞叾浠栧叧閿瘝銆�",
+ "lang.zh": "涓枃",
+ "lang.en": "English",
+ "lang.ko": "頃滉淡鞏�",
+ "footer.copyright": "涓婃捣浜敵 Copyright 漏 2026",
+ "welcome.title": "娓╅Θ鎻愮ず",
+ "welcome.p1": "1銆佽杈撳叆鍨冨溇姝e父鐨勪腑鏂囧悕绉帮紙鍖呭惈鏉愯川锛夛紝濡傜幓鐠冪摱锛屼竴娆℃�у鏂欐澂銆侀櫠鐡风绛夈��",
+ "welcome.p2": "2銆佺敓娲诲瀮鍦惧垎绫荤殑鍏蜂綋鍒嗙被鏍囧噯锛氭槸鏍规嵁缁忔祹绀句細鍙戝睍姘村钩銆佺敓娲诲瀮鍦剧壒鎬у拰澶勭悊鍒╃敤鏂规硶浜堜互缁嗗寲璋冩暣鐨勩��",
+ "welcome.p3": "3銆佹湰鏌ヨ绯荤粺浠呬緵鍙傝�冿紝鍏蜂綋鍒嗙被瑕佹眰浠ュ睘鍦颁笓涓氱鐞嗛儴闂ㄤ负鍑嗐��",
+ "welcome.confirm": "鐭ラ亾浜�",
+ "disposal.suggestLabel": "寤鸿鎶曟斁鑷筹細",
+ "disposal.tipsTitle": "灏忕鏅�",
+ "cat.recyclable": "鍙洖鏀剁墿",
+ "cat.recyclable.desc": "鏄寚搴熺焊寮犮�佸簾濉戞枡銆佸簾鐜荤拑鍒跺搧銆佸簾閲戝睘銆佸簾缁囩墿绛夐�傚疁鍥炴敹銆佸彲寰幆鍒╃敤鐨勭敓娲诲簾寮冪墿銆�",
+ "cat.recyclable.standard": "1. 杞绘姇杞绘斁\n2. 娓呮磥骞茬嚗锛岄伩鍏嶆薄鏌撱�俓n3. 搴熺焊绫诲敖閲忓钩鏁达紝淇濇寔骞茬嚗銆俓n4. 濉戞枡绫诲簲鍘婚櫎娈嬬暀鐗╋紝娲楀噣鏅惧共銆俓n5. 绔嬩綋鍖呰鐗╄娓呯┖鍐呭鐗╋紝娓呮磥鍚庡帇鎵佹姇鏀� \n6. 鏈夊皷閿愯竟瑙掔殑,搴斿寘瑁瑰悗鎶曟斁銆俓n7. 閲戝睘绫诲簲鍘婚櫎娈嬬暀鐗╋紝鍘嬫墎鍚庢姇鏀俱�俓n8. 缁囩墿绫诲簲娲楀噣鏅惧共锛屾姌鍙犳暣榻愩��",
+ "cat.hazardous": "鏈夊鍨冨溇",
+ "cat.hazardous.desc": "瀵逛汉浣撳仴搴锋垨鑷劧鐜閫犳垚鐩存帴鎴栨綔鍦ㄥ嵄瀹崇殑鐢熸椿搴熷純鐗┿�備富瑕佸寘鎷細搴熺數姹犮�佸簾鐏銆佸簾鑽搧銆佸簾娌规紗鍙婂叾瀹瑰櫒绛夈��",
+ "cat.hazardous.standard": "1. 鏈夊鍨冨溇搴旇交鏀撅紝鏄撶牬鎹熺殑搴斿寘瑁瑰悗鎶曟斁\n2. 搴熺數姹犲簲淇濇寔瀹屾暣锛屼笉瑕佹媶瑙n3. 搴熺伅绠″簲闃叉鐮寸锛岀敤绾稿紶鍖呰9鍚庢姇鏀綷n4. 搴熻嵂鍝佸簲杩炲悓鍖呰涓�璧锋姇鏀綷n5. 搴熸补婕嗘《搴斿瘑灏佸悗鎶曟斁\n6. 鎶曟斁鏃跺簲娉ㄦ剰瀹夊叏锛岄伩鍏嶆硠婕廫n7. 濡傛槗鎸ュ彂锛岃瀵嗗皝鍚庢姇鏀�",
+ "cat.wet": "婀垮瀮鍦�",
+ "cat.wet.desc": "鍗虫槗鑵愬瀮鍦俱�佹槗鑵愮殑鐢熸椿鐗╄川鍜岀敓娲诲簾寮冪墿銆備富瑕佸寘鎷細椋熸潗搴熸枡銆佸墿鑿滃墿楗�佽繃鏈熼鍝併�佺摐鐨灉鏍搞�佽姳鍗夌豢妞嶃�佷腑鑽嵂娓g瓑銆�",
+ "cat.wet.standard": "1. 婀垮瀮鍦惧簲娌ュ共姘村垎鍚庢姇鏀綷n2. 绾祦璐ㄧ殑椋熺墿鍨冨溇锛屽鐗涘ザ绛夛紝搴旂洿鎺ュ�掑叆涓嬫按鍙n3. 鏈夊寘瑁呯墿鐨勬箍鍨冨溇搴斿皢鍖呰鐗╁幓闄ゅ悗鍒嗙被鎶曟斁\n4. 澶ч澶淬�佽礉澹崇被搴斾綔涓哄共鍨冨溇鎶曟斁\n5. 椁愬帹鍨冨溇搴斿幓闄ゆ潅鐗╁悗鎶曟斁",
+ "cat.dry": "骞插瀮鍦�",
+ "cat.dry.desc": "闄ゅ彲鍥炴敹鐗┿�佹湁瀹冲瀮鍦俱�佹箍鍨冨溇浠ュ鐨勫叾浠栫敓娲诲簾寮冪墿銆�",
+ "cat.dry.standard": "1. 灏介噺娌ュ共姘村垎鍚庢姇鏀綷n2. 闅句互杈ㄨ瘑绫诲埆鐨勭敓娲诲瀮鍦惧簲鎶曞叆骞插瀮鍦惧鍣╘n3. 浣撶Н杈冨ぇ鐨勫瀮鍦惧簲閫傚綋鍒嗚В鍚庢姇鏀綷n4. 涓�娆℃�ч鍏枫�佺焊宸剧瓑搴斾綔涓哄共鍨冨溇鎶曟斁\n5. 鐑熻拏搴斿畬鍏ㄧ唲鐏悗鎶曟斁",
+ "disposal.suggest.recyclable": "鍙洖鏀剁墿",
+ "disposal.line1.recyclable": "璇蜂繚鎸佹竻娲佸共鐕ワ紝閬垮厤姹℃煋銆�",
+ "disposal.line2.recyclable": "鎶曟斁鍓嶈鍘婚櫎娈嬬暀鐗╋紝鍘嬫墎鍑忓銆�",
+ "disposal.tip1.recyclable": "鍙洖鏀剁墿缁忓洖鏀跺鐞嗗悗锛屽彲閲嶆柊鍒舵垚鏂扮殑浜у搧锛岃妭绾﹁祫婧愩��",
+ "disposal.tip2.recyclable": "1涓鏂欑摱鍥炴敹鍚庡彲鑺傜渷瓒冲鐐逛寒60鐡︾伅娉�3灏忔椂鐨勭數鑳姐��",
+ "disposal.tip3.recyclable": "鍥炴敹1鍚ㄥ簾绾稿彲鑺傜渷17妫垫爲銆�",
+ "disposal.tip4.recyclable": "鍨冨溇鍒嗙被浠庣偣婊村仛璧凤紝璁╄祫婧愬惊鐜埄鐢ㄣ��",
+ "disposal.suggest.hazardous": "鏈夊鍨冨溇",
+ "disposal.line1.hazardous": "璇疯交鏀撅紝鏄撶牬鎹熺殑搴斿寘瑁瑰悗鎶曟斁銆�",
+ "disposal.line2.hazardous": "搴熺數姹犮�佸簾鐏绛夊簲淇濇寔瀹屾暣锛屼笉瑕佹媶瑙c��",
+ "disposal.tip1.hazardous": "鏈夊鍨冨溇鍚湁瀵逛汉浣撳仴搴锋垨鐜鏈夊鐨勭墿璐紝闇�鐗规畩澶勭悊銆�",
+ "disposal.tip2.hazardous": "1鑺傚簾鐢垫睜闅忔剰涓㈠純锛屽彲鑳芥薄鏌�1骞虫柟绫冲湡鍦�50骞淬��",
+ "disposal.tip3.hazardous": "搴熻崸鍏夌伅绠″惈鏈夋睘锛岀牬纰庡悗浼氭薄鏌撶┖姘斿拰鍦熷¥銆�",
+ "disposal.tip4.hazardous": "姝g‘鎶曟斁鏈夊鍨冨溇锛屼繚鎶ゆ垜浠殑鍋ュ悍涓庣幆澧冦��",
+ "disposal.suggest.wet": "婀垮瀮鍦�",
+ "disposal.line1.wet": "璇锋播骞叉按鍒嗗悗鎶曟斁锛岀函娴佽川搴斿�掑叆涓嬫按鍙c��",
+ "disposal.line2.wet": "鏈夊寘瑁呯墿鐨勬箍鍨冨溇搴斿幓闄ゅ寘瑁呭悗鍒嗙被鎶曟斁銆�",
+ "disposal.tip1.wet": "婀垮瀮鍦剧粡鐢熷寲澶勭悊鍚庡彲杞寲涓烘湁鏈鸿偉鏂欍��",
+ "disposal.tip2.wet": "涓婃捣姣忓ぉ浜х敓鐨勬箍鍨冨溇绾�1涓囧惃锛屾纭垎绫绘剰涔夐噸澶с��",
+ "disposal.tip3.wet": "婀垮瀮鍦炬姇鏀惧墠搴斿敖閲忔播骞诧紝鍑忓皯娓楁护娑蹭骇鐢熴��",
+ "disposal.tip4.wet": "鍓╄彍鍓╅キ鍙樺簾涓哄疂锛屽姪鍔涜祫婧愬惊鐜埄鐢ㄣ��",
+ "disposal.suggest.dry": "骞插瀮鍦�",
+ "disposal.line1.dry": "璇峰敖閲忔播骞叉按鍒嗗悗鎶曟斁銆�",
+ "disposal.line2.dry": "闅句互杈ㄨ瘑绫诲埆鐨勭敓娲诲瀮鍦惧簲鎶曞叆骞插瀮鍦俱��",
+ "disposal.tip1.dry": "骞插瀮鍦句富瑕侀�氳繃鐒氱儳鎴栧~鍩嬫柟寮忓鐞嗐��",
+ "disposal.tip2.dry": "鍑忓皯骞插瀮鍦句骇鐢燂紝浠庢簮澶村仛濂藉瀮鍦惧垎绫汇��",
+ "disposal.tip3.dry": "绾稿肪銆佺儫钂傘�佷竴娆℃�ч鍏风瓑閮藉睘浜庡共鍨冨溇銆�",
+ "disposal.tip4.dry": "鍨冨溇鍒嗙被锛岃鍩庡競鏇寸編涓姐��",
+ "lang.ja": "鏃ユ湰瑾�",
+ "item.milkBox": "鐗涘ザ鐩�",
+ "item.plastic": "濉戞枡",
+ "item.glassBottle": "鐜荤拑鐡�",
+ "item.glass": "鐜荤拑",
+ "item.paper": "绾�",
+ "item.clothes": "琛f湇",
+ "item.brokenGlass": "纰庣幓鐠�",
+ "item.can": "鏄撴媺缃�",
+ "item.plasticBox": "濉戞枡鐩�",
+ "item.foamBoard": "娉℃搏鏉�",
+ "item.powerBank": "鍏呯數瀹�",
+ "item.shoes": "闉嬪瓙",
+ "item.paperBox": "绾哥洅",
+ "item.foamBox": "娉℃搏绠�",
+ "item.glassCup": "鐜荤拑鏉�",
+ "item.newspaper": "鎶ョ焊",
+ "item.plasticCup": "濉戞枡鏉�",
+ "item.wire": "鐢电嚎",
+ "item.dataCable": "鏁版嵁绾�",
+ "item.waterBottle": "鐭挎硥姘寸摱",
+ "item.pillow": "鏋曞ご",
+ "item.blade": "鍒�鐗�",
+ "item.screw": "铻轰笣",
+ "item.foamPlastic": "娉℃搏濉戞枡",
+ "item.yogurtTetraPak": "閰稿ザ鍒╀箰鍖呰鐩�",
+ "item.paperBag": "绾歌",
+ "item.cosmeticPlasticBottle": "鍖栧鍝佸鏂欑┖鐡�",
+ "item.leatherShoes": "鐨瀷",
+ "item.cosmeticGlassBottle": "鍖栧鍝佺幓鐠冪┖鐡�",
+ "item.wineBottle": "閰掔摱",
+ "item.chargingCable": "鍏呯數绾�",
+ "item.flyer": "骞垮憡鍗�",
+ "item.wastePlastic": "搴熷鏂�",
+ "item.cigaretteBox": "鐑熺洅",
+ "item.charger": "鍏呯數鍣�",
+ "item.book": "涔︽湰",
+ "item.beerBottle": "鍟ら厭鐡�",
+ "item.cardboardBox": "绾告澘绠�",
+ "item.woodChopsticks": "鏈ㄧ瀛�",
+ "item.plushToy": "姣涚粧鐜╁叿",
+ "item.bedSheet": "琚崟",
+ "item.scissors": "鍓垁",
+ "item.drinkPlasticBottle": "楗枡濉戞枡鐡�",
+ "item.fabric": "甯�",
+ "item.dehumidifierBox": "闄ゆ箍鐩�",
+ "item.magnet": "鍚搁搧鐭�",
+ "item.plasticWrap": "濉戞枡鍖呰绾�",
+ "item.quilt": "琚瓙",
+ "item.tetraPak": "鍒╀箰鍖呰",
+ "item.basketball": "绡悆",
+ "item.aluminumFoil": "閾濈當",
+ "item.socket": "鎻掑骇",
+ "item.iron": "閾�",
+ "item.key": "閽ュ寵",
+ "item.printingPaper": "鎵撳嵃绾�",
+ "item.metal": "閲戝睘",
+ "item.whitePaper": "鐧界焊",
+ "item.packagingBox": "鍖呰绾哥洅",
+ "item.plasticLid": "濉戞枡鐩�",
+ "item.envelope": "淇″皝",
+ "item.medicinePackaging": "鑽搧鍖呰",
+ "item.medicineBottle": "鑽摱",
+ "item.lightBulb": "鐏场",
+ "item.paintBucket": "娌规紗妗�",
+ "item.medicine": "鑽搧",
+ "item.expiredMedicine": "杩囨湡鑽�",
+ "item.rechargeableBattery": "鍏呯數鐢垫睜",
+ "item.nailPolish": "鎸囩敳娌�",
+ "item.storageBattery": "钃勭數姹�",
+ "item.emptyMedicineBottle": "绌鸿嵂鐡�",
+ "item.hazardousWaste": "鏈夊鍨冨溇",
+ "item.expiredMedicine2": "杩囨湡鑽搧",
+ "item.wasteMedicine": "搴熻嵂鍝�",
+ "item.lightTube": "鐏",
+ "item.fluorescentTube": "鑽у厜鐏",
+ "item.niCdBattery": "闀嶉晧鐢垫睜",
+ "item.photo": "鐓х墖",
+ "item.fluorescentLamp": "鑽у厜鐏�",
+ "item.hairDyeShell": "鏌撳彂鍓傚3",
+ "item.eyeDrops": "鐪艰嵂姘�",
+ "item.energySavingLamp": "鑺傝兘鐏�",
+ "item.insecticide": "鏉�铏墏",
+ "item.medicineTablet": "鑽墖",
+ "item.medicineTabletBox": "鑽墖鐩�",
+ "item.oralLiquidBottle": "鍙f湇娑茶嵂鐡�",
+ "item.wasteMedicineBottle": "搴熻嵂鐡�",
+ "item.paint": "娌规紗",
+ "item.buttonBattery": "绾芥墸鐢垫睜",
+ "item.contraceptive": "閬垮瓡鑽�",
+ "item.eyeDropsBottle": "鐪艰嵂姘寸摱",
+ "item.film": "鑳剁墖",
+ "item.capsule": "鑳跺泭",
+ "item.mercuryThermometer": "姘撮摱娓╁害璁�",
+ "item.ratPoison": "鑰侀紶鑽�",
+ "item.capsuleBlister": "鑳跺泭鑽墖搴曟澘",
+ "item.hairDyeCan": "鏌撳彂鍓傜綈",
+ "item.energySavingBulb": "鑺傝兘鐏场",
+ "item.allExpiredMedicine": "鍚勭被杩囨湡鑽搧",
+ "item.incandescentBulb": "鐧界偨鐏场",
+ "item.phoneBattery": "鎵嬫満鐢垫睜",
+ "item.disinfectantBottle": "娑堟瘨娑茬摱",
+ "item.expiredTablets": "杩囨湡鑽墖",
+ "item.coldMedicine": "鎰熷啋鑽�",
+ "item.disinfectant84Bottle": "84娑堟瘨娑茬┖鐡�",
+ "item.nailPolishBottle": "鎸囩敳娌圭摱",
+ "item.sprayCan": "鏉�姣掑柗闆剧綈",
+ "item.photoNegative": "鐩哥墖搴曠墖",
+ "item.chinesePatentMedicine": "涓垚鑽�",
+ "item.filmRoll": "鑳跺嵎",
+ "item.medicineShell": "鑽搧澹冲瓙",
+ "item.mercury": "姘撮摱",
+ "item.photo2": "鐩哥墖",
+ "item.wastePaintBucket": "搴熸补婕嗘《",
+ "item.expiredDrug": "杩囨湡鑽墿",
+ "item.medicineBlister": "鑽搧閾濆鏉�",
+ "item.cockroachMedicine": "锜戣瀭鑽�",
+ "item.cockroachBall": "锜戣瀭涓�",
+ "item.capsuleTablet": "鑳跺泭鑽墖",
+ "item.disinfectantTablet": "娑堟瘨鑽墖",
+ "item.energySavingTube": "鑺傝兘鐏",
+ "item.melonSeedShell": "鐡滃瓙澹�",
+ "item.eggShell": "楦¤泲澹�",
+ "item.cornCob": "鐜夌背妫�",
+ "item.eggshell": "铔嬪3",
+ "item.corn": "鐜夌背",
+ "item.walnut": "鏍告",
+ "item.peanutShell": "鑺辩敓澹�",
+ "item.tea": "鑼跺彾",
+ "item.lobsterShell": "榫欒櫨澹�",
+ "item.crayfish": "灏忛緳铏�",
+ "item.crabShell": "锜瑰3",
+ "item.chickenBone": "楦¢澶�",
+ "item.melonSeed": "鐡滃瓙",
+ "item.crabShell2": "铻冭煿澹�",
+ "item.cookedCornCob": "鐔熺帀绫虫",
+ "item.pistachioShell": "寮�蹇冩灉澹�",
+ "item.crayfishShell": "灏忛緳铏惧3",
+ "item.edamameShell": "姣涜眴澹�",
+ "item.shrimpShell": "闇炲3",
+ "item.bananaPeel": "棣欒晧鐨�",
+ "item.watermelonRind": "瑗跨摐鐨�",
+ "item.chestnutShell": "鏍楀瓙澹�",
+ "item.fishBone": "楸奸澶�",
+ "item.lobster": "榫欒櫨",
+ "item.cornCore": "鐜夌背鑺�",
+ "item.melonSeedPiece": "鐡滃瓙鐗�",
+ "item.flower": "鑺�",
+ "item.coffeeGrounds": "鍜栧暋娓�",
+ "item.porkRibs": "鎺掗",
+ "item.zongzi": "绮藉瓙",
+ "item.herbalDregs": "涓嵂娓�",
+ "item.egg": "楦¤泲",
+ "item.crab": "铻冭煿",
+ "item.lycheeShell": "鑽旀灊澹�",
+ "item.peach": "妗冨瓙",
+ "item.plumPit": "璇濇鏍�",
+ "item.jujubePit": "鏋f牳",
+ "item.chickenBone2": "楦¢",
+ "item.expiredFood": "杩囨湡椋熷搧",
+ "item.fishBone2": "楸奸",
+ "item.apple": "鑻规灉",
+ "item.lycheePit": "鑽旀灊鏍�",
+ "item.bayberry": "鏉ㄦ",
+ "item.watermelonSeed": "瑗跨摐绫�",
+ "item.chestnutShell2": "鏉挎牀澹�",
+ "item.cockroach2": "锜戣瀭",
+ "item.fruitPeel": "鏋滅毊",
+ "item.mangoPit": "鑺掓灉鏍�",
+ "item.peanut": "鑺辩敓",
+ "item.driedPeanutShell": "骞茶姳鐢熷3",
+ "item.biscuit": "楗煎共",
+ "item.watermelon": "瑗跨摐",
+ "item.freshFlower": "椴滆姳",
+ "item.redJujubePit": "绾㈡灒鏍�",
+ "item.lusuji": "鑺︾ǚ",
+ "item.appleCore": "鑻规灉鏍�",
+ "item.waterBambooPeel": "鑼櫧鐨�",
+ "item.bread": "闈㈠寘",
+ "item.banana": "棣欒晧",
+ "item.teaResidue": "鑼跺彾娓�",
+ "item.plasticBag": "濉戞枡琚�",
+ "item.zongziLeaf": "绮藉彾",
+ "item.walnutShell": "鏍告澹�",
+ "item.hair": "澶村彂",
+ "item.shell": "璐濆3",
+ "item.sanitaryPad": "鍗敓宸�",
+ "item.condom": "閬垮瓡濂�",
+ "item.chewingGum": "鍙i绯�",
+ "item.lighter": "鎵撶伀鏈�",
+ "item.coconutShell": "妞板瓙澹�",
+ "item.catLitter": "鐚爞",
+ "item.faceMask": "闈㈣啘",
+ "item.tissue": "椁愬肪绾�",
+ "item.bigBone": "澶ч澶�",
+ "item.milkTeaCup": "濂惰尪鏉�",
+ "item.paperTowel": "绾稿肪",
+ "item.clamShell": "铔よ湂澹�",
+ "item.zongziLeaf2": "绮藉瓙鍙�",
+ "item.cornHusk": "鐜夌背鐨�",
+ "item.straw": "鍚哥",
+ "item.teaBag": "鑼跺寘",
+ "item.sugarcanePeel": "鐢樿敆鐨�",
+ "item.desiccant": "骞茬嚗鍓�",
+ "item.disposableChopsticks": "涓�娆℃�х瀛�",
+ "item.cornShell": "鐜夌背澹�",
+ "item.cigarette": "鐑熻拏",
+ "item.wetWipe": "婀跨焊宸�",
+ "item.durianShell": "姒磋幉澹�",
+ "item.toiletPaper": "鍗敓绾�",
+ "item.bigWalnutShell": "澶ф牳妗冨3",
+ "item.nail": "鎸囩敳",
+ "item.packagingBag": "鍖呰琚�",
+ "item.lipstick": "鍙g孩",
+ "item.disposableCup": "涓�娆℃�ф澂瀛�",
+ "item.snailShell": "铻鸿洺澹�",
+ "item.toothbrush": "鐗欏埛",
+ "item.takeoutBox": "澶栧崠椁愮洅",
+ "item.durian": "姒磋幉",
+ "item.diaper": "灏夸笉婀�",
+ "item.trashBag": "鍨冨溇琚�",
+ "item.toothpasteTube": "鐗欒啅鐨�",
+ "item.icePack": "鍐拌",
+ "item.sock": "琚滃瓙",
+ "item.pen": "绗�",
+ "item.diaper2": "绾稿翱瑁�",
+ "item.durianPit": "姒磋幉鏍�",
+ "item.disposableLunchBox": "涓�娆℃�ч鐩�",
+ "item.teaBag2": "鑼跺彾鍖�",
+ "item.mask": "鍙g僵",
+ "item.underwear": "鍐呰¥",
+ "item.towel": "姣涘肪",
+ "item.diaper3": "灏垮竷",
+ "item.ceramicBowl": "闄剁摲纰�",
+ "item.penRefill": "绗旇姱",
+ "item.dirtyPlasticBag": "鑲剰濉戞枡琚�",
+ "item.paperClip": "鍥炲舰閽�",
+ "item.toothpick": "鐗欑",
+ "item.foodPackagingBag": "椋熷搧鍖呰琚�",
+ "item.watercolorPen": "姘村僵绗�",
+ "item.cottonSwab": "妫夌"
+}
diff --git a/config/items.json b/config/items.json
new file mode 100644
index 0000000..5a49033
--- /dev/null
+++ b/config/items.json
@@ -0,0 +1,1202 @@
+[
+ {
+ "id": "milk-box",
+ "nameKey": "item.milkBox",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "plastic",
+ "nameKey": "item.plastic",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "glass-bottle",
+ "nameKey": "item.glassBottle",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "glass",
+ "nameKey": "item.glass",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "paper",
+ "nameKey": "item.paper",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "clothes",
+ "nameKey": "item.clothes",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "broken-glass",
+ "nameKey": "item.brokenGlass",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "can",
+ "nameKey": "item.can",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "plastic-box",
+ "nameKey": "item.plasticBox",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "foam-board",
+ "nameKey": "item.foamBoard",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "power-bank",
+ "nameKey": "item.powerBank",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "shoes",
+ "nameKey": "item.shoes",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "paper-box",
+ "nameKey": "item.paperBox",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "foam-box",
+ "nameKey": "item.foamBox",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "glass-cup",
+ "nameKey": "item.glassCup",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "newspaper",
+ "nameKey": "item.newspaper",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "plastic-cup",
+ "nameKey": "item.plasticCup",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "wire",
+ "nameKey": "item.wire",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "data-cable",
+ "nameKey": "item.dataCable",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "water-bottle",
+ "nameKey": "item.waterBottle",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "pillow",
+ "nameKey": "item.pillow",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "blade",
+ "nameKey": "item.blade",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "screw",
+ "nameKey": "item.screw",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "foam-plastic",
+ "nameKey": "item.foamPlastic",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "yogurt-tetra-pak",
+ "nameKey": "item.yogurtTetraPak",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "paper-bag",
+ "nameKey": "item.paperBag",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "cosmetic-plastic-bottle",
+ "nameKey": "item.cosmeticPlasticBottle",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "leather-shoes",
+ "nameKey": "item.leatherShoes",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "cosmetic-glass-bottle",
+ "nameKey": "item.cosmeticGlassBottle",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "wine-bottle",
+ "nameKey": "item.wineBottle",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "charging-cable",
+ "nameKey": "item.chargingCable",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "flyer",
+ "nameKey": "item.flyer",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "waste-plastic",
+ "nameKey": "item.wastePlastic",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "cigarette-box",
+ "nameKey": "item.cigaretteBox",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "charger",
+ "nameKey": "item.charger",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "book",
+ "nameKey": "item.book",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "beer-bottle",
+ "nameKey": "item.beerBottle",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "cardboard-box",
+ "nameKey": "item.cardboardBox",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "wood-chopsticks",
+ "nameKey": "item.woodChopsticks",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "plush-toy",
+ "nameKey": "item.plushToy",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "bed-sheet",
+ "nameKey": "item.bedSheet",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "scissors",
+ "nameKey": "item.scissors",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "drink-plastic-bottle",
+ "nameKey": "item.drinkPlasticBottle",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "fabric",
+ "nameKey": "item.fabric",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "dehumidifier-box",
+ "nameKey": "item.dehumidifierBox",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "magnet",
+ "nameKey": "item.magnet",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "plastic-wrap",
+ "nameKey": "item.plasticWrap",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "quilt",
+ "nameKey": "item.quilt",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "tetra-pak",
+ "nameKey": "item.tetraPak",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "basketball",
+ "nameKey": "item.basketball",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "aluminum-foil",
+ "nameKey": "item.aluminumFoil",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "socket",
+ "nameKey": "item.socket",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "iron",
+ "nameKey": "item.iron",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "key",
+ "nameKey": "item.key",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "printing-paper",
+ "nameKey": "item.printingPaper",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "metal",
+ "nameKey": "item.metal",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "white-paper",
+ "nameKey": "item.whitePaper",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "packaging-box",
+ "nameKey": "item.packagingBox",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "plastic-lid",
+ "nameKey": "item.plasticLid",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "envelope",
+ "nameKey": "item.envelope",
+ "categoryId": "recyclable"
+ },
+ {
+ "id": "medicine-packaging",
+ "nameKey": "item.medicinePackaging",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "medicine-bottle",
+ "nameKey": "item.medicineBottle",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "light-bulb",
+ "nameKey": "item.lightBulb",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "paint-bucket",
+ "nameKey": "item.paintBucket",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "medicine",
+ "nameKey": "item.medicine",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "expired-medicine",
+ "nameKey": "item.expiredMedicine",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "rechargeable-battery",
+ "nameKey": "item.rechargeableBattery",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "nail-polish",
+ "nameKey": "item.nailPolish",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "storage-battery",
+ "nameKey": "item.storageBattery",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "empty-medicine-bottle",
+ "nameKey": "item.emptyMedicineBottle",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "hazardous-waste",
+ "nameKey": "item.hazardousWaste",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "expired-medicine2",
+ "nameKey": "item.expiredMedicine2",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "waste-medicine",
+ "nameKey": "item.wasteMedicine",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "light-tube",
+ "nameKey": "item.lightTube",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "fluorescent-tube",
+ "nameKey": "item.fluorescentTube",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "ni-cd-battery",
+ "nameKey": "item.niCdBattery",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "photo",
+ "nameKey": "item.photo",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "fluorescent-lamp",
+ "nameKey": "item.fluorescentLamp",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "hair-dye-shell",
+ "nameKey": "item.hairDyeShell",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "eye-drops",
+ "nameKey": "item.eyeDrops",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "energy-saving-lamp",
+ "nameKey": "item.energySavingLamp",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "insecticide",
+ "nameKey": "item.insecticide",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "medicine-tablet",
+ "nameKey": "item.medicineTablet",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "medicine-tablet-box",
+ "nameKey": "item.medicineTabletBox",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "oral-liquid-bottle",
+ "nameKey": "item.oralLiquidBottle",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "waste-medicine-bottle",
+ "nameKey": "item.wasteMedicineBottle",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "paint",
+ "nameKey": "item.paint",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "button-battery",
+ "nameKey": "item.buttonBattery",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "contraceptive",
+ "nameKey": "item.contraceptive",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "eye-drops-bottle",
+ "nameKey": "item.eyeDropsBottle",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "film",
+ "nameKey": "item.film",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "capsule",
+ "nameKey": "item.capsule",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "mercury-thermometer",
+ "nameKey": "item.mercuryThermometer",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "rat-poison",
+ "nameKey": "item.ratPoison",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "capsule-blister",
+ "nameKey": "item.capsuleBlister",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "hair-dye-can",
+ "nameKey": "item.hairDyeCan",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "energy-saving-bulb",
+ "nameKey": "item.energySavingBulb",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "all-expired-medicine",
+ "nameKey": "item.allExpiredMedicine",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "incandescent-bulb",
+ "nameKey": "item.incandescentBulb",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "phone-battery",
+ "nameKey": "item.phoneBattery",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "disinfectant-bottle",
+ "nameKey": "item.disinfectantBottle",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "expired-tablets",
+ "nameKey": "item.expiredTablets",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "cold-medicine",
+ "nameKey": "item.coldMedicine",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "disinfectant84-bottle",
+ "nameKey": "item.disinfectant84Bottle",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "nail-polish-bottle",
+ "nameKey": "item.nailPolishBottle",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "spray-can",
+ "nameKey": "item.sprayCan",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "photo-negative",
+ "nameKey": "item.photoNegative",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "chinese-patent-medicine",
+ "nameKey": "item.chinesePatentMedicine",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "film-roll",
+ "nameKey": "item.filmRoll",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "medicine-shell",
+ "nameKey": "item.medicineShell",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "mercury",
+ "nameKey": "item.mercury",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "photo2",
+ "nameKey": "item.photo2",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "waste-paint-bucket",
+ "nameKey": "item.wastePaintBucket",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "expired-drug",
+ "nameKey": "item.expiredDrug",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "medicine-blister",
+ "nameKey": "item.medicineBlister",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "cockroach-medicine",
+ "nameKey": "item.cockroachMedicine",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "cockroach-ball",
+ "nameKey": "item.cockroachBall",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "capsule-tablet",
+ "nameKey": "item.capsuleTablet",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "disinfectant-tablet",
+ "nameKey": "item.disinfectantTablet",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "energy-saving-tube",
+ "nameKey": "item.energySavingTube",
+ "categoryId": "hazardous"
+ },
+ {
+ "id": "melon-seed-shell",
+ "nameKey": "item.melonSeedShell",
+ "categoryId": "wet"
+ },
+ {
+ "id": "egg-shell",
+ "nameKey": "item.eggShell",
+ "categoryId": "wet"
+ },
+ {
+ "id": "corn-cob",
+ "nameKey": "item.cornCob",
+ "categoryId": "wet"
+ },
+ {
+ "id": "eggshell",
+ "nameKey": "item.eggshell",
+ "categoryId": "wet"
+ },
+ {
+ "id": "corn",
+ "nameKey": "item.corn",
+ "categoryId": "wet"
+ },
+ {
+ "id": "walnut",
+ "nameKey": "item.walnut",
+ "categoryId": "wet"
+ },
+ {
+ "id": "peanut-shell",
+ "nameKey": "item.peanutShell",
+ "categoryId": "wet"
+ },
+ {
+ "id": "tea",
+ "nameKey": "item.tea",
+ "categoryId": "wet"
+ },
+ {
+ "id": "lobster-shell",
+ "nameKey": "item.lobsterShell",
+ "categoryId": "wet"
+ },
+ {
+ "id": "crayfish",
+ "nameKey": "item.crayfish",
+ "categoryId": "wet"
+ },
+ {
+ "id": "crab-shell",
+ "nameKey": "item.crabShell",
+ "categoryId": "wet"
+ },
+ {
+ "id": "chicken-bone",
+ "nameKey": "item.chickenBone",
+ "categoryId": "wet"
+ },
+ {
+ "id": "melon-seed",
+ "nameKey": "item.melonSeed",
+ "categoryId": "wet"
+ },
+ {
+ "id": "crab-shell2",
+ "nameKey": "item.crabShell2",
+ "categoryId": "wet"
+ },
+ {
+ "id": "cooked-corn-cob",
+ "nameKey": "item.cookedCornCob",
+ "categoryId": "wet"
+ },
+ {
+ "id": "pistachio-shell",
+ "nameKey": "item.pistachioShell",
+ "categoryId": "wet"
+ },
+ {
+ "id": "crayfish-shell",
+ "nameKey": "item.crayfishShell",
+ "categoryId": "wet"
+ },
+ {
+ "id": "edamame-shell",
+ "nameKey": "item.edamameShell",
+ "categoryId": "wet"
+ },
+ {
+ "id": "shrimp-shell",
+ "nameKey": "item.shrimpShell",
+ "categoryId": "wet"
+ },
+ {
+ "id": "banana-peel",
+ "nameKey": "item.bananaPeel",
+ "categoryId": "wet"
+ },
+ {
+ "id": "watermelon-rind",
+ "nameKey": "item.watermelonRind",
+ "categoryId": "wet"
+ },
+ {
+ "id": "chestnut-shell",
+ "nameKey": "item.chestnutShell",
+ "categoryId": "wet"
+ },
+ {
+ "id": "fish-bone",
+ "nameKey": "item.fishBone",
+ "categoryId": "wet"
+ },
+ {
+ "id": "lobster",
+ "nameKey": "item.lobster",
+ "categoryId": "wet"
+ },
+ {
+ "id": "corn-core",
+ "nameKey": "item.cornCore",
+ "categoryId": "wet"
+ },
+ {
+ "id": "melon-seed-piece",
+ "nameKey": "item.melonSeedPiece",
+ "categoryId": "wet"
+ },
+ {
+ "id": "flower",
+ "nameKey": "item.flower",
+ "categoryId": "wet"
+ },
+ {
+ "id": "coffee-grounds",
+ "nameKey": "item.coffeeGrounds",
+ "categoryId": "wet"
+ },
+ {
+ "id": "pork-ribs",
+ "nameKey": "item.porkRibs",
+ "categoryId": "wet"
+ },
+ {
+ "id": "zongzi",
+ "nameKey": "item.zongzi",
+ "categoryId": "wet"
+ },
+ {
+ "id": "herbal-dregs",
+ "nameKey": "item.herbalDregs",
+ "categoryId": "wet"
+ },
+ {
+ "id": "egg",
+ "nameKey": "item.egg",
+ "categoryId": "wet"
+ },
+ {
+ "id": "crab",
+ "nameKey": "item.crab",
+ "categoryId": "wet"
+ },
+ {
+ "id": "lychee-shell",
+ "nameKey": "item.lycheeShell",
+ "categoryId": "wet"
+ },
+ {
+ "id": "peach",
+ "nameKey": "item.peach",
+ "categoryId": "wet"
+ },
+ {
+ "id": "plum-pit",
+ "nameKey": "item.plumPit",
+ "categoryId": "wet"
+ },
+ {
+ "id": "jujube-pit",
+ "nameKey": "item.jujubePit",
+ "categoryId": "wet"
+ },
+ {
+ "id": "chicken-bone2",
+ "nameKey": "item.chickenBone2",
+ "categoryId": "wet"
+ },
+ {
+ "id": "expired-food",
+ "nameKey": "item.expiredFood",
+ "categoryId": "wet"
+ },
+ {
+ "id": "fish-bone2",
+ "nameKey": "item.fishBone2",
+ "categoryId": "wet"
+ },
+ {
+ "id": "apple",
+ "nameKey": "item.apple",
+ "categoryId": "wet"
+ },
+ {
+ "id": "lychee-pit",
+ "nameKey": "item.lycheePit",
+ "categoryId": "wet"
+ },
+ {
+ "id": "bayberry",
+ "nameKey": "item.bayberry",
+ "categoryId": "wet"
+ },
+ {
+ "id": "watermelon-seed",
+ "nameKey": "item.watermelonSeed",
+ "categoryId": "wet"
+ },
+ {
+ "id": "chestnut-shell2",
+ "nameKey": "item.chestnutShell2",
+ "categoryId": "wet"
+ },
+ {
+ "id": "cockroach2",
+ "nameKey": "item.cockroach2",
+ "categoryId": "wet"
+ },
+ {
+ "id": "fruit-peel",
+ "nameKey": "item.fruitPeel",
+ "categoryId": "wet"
+ },
+ {
+ "id": "mango-pit",
+ "nameKey": "item.mangoPit",
+ "categoryId": "wet"
+ },
+ {
+ "id": "peanut",
+ "nameKey": "item.peanut",
+ "categoryId": "wet"
+ },
+ {
+ "id": "dried-peanut-shell",
+ "nameKey": "item.driedPeanutShell",
+ "categoryId": "wet"
+ },
+ {
+ "id": "biscuit",
+ "nameKey": "item.biscuit",
+ "categoryId": "wet"
+ },
+ {
+ "id": "watermelon",
+ "nameKey": "item.watermelon",
+ "categoryId": "wet"
+ },
+ {
+ "id": "fresh-flower",
+ "nameKey": "item.freshFlower",
+ "categoryId": "wet"
+ },
+ {
+ "id": "red-jujube-pit",
+ "nameKey": "item.redJujubePit",
+ "categoryId": "wet"
+ },
+ {
+ "id": "lusuji",
+ "nameKey": "item.lusuji",
+ "categoryId": "wet"
+ },
+ {
+ "id": "apple-core",
+ "nameKey": "item.appleCore",
+ "categoryId": "wet"
+ },
+ {
+ "id": "water-bamboo-peel",
+ "nameKey": "item.waterBambooPeel",
+ "categoryId": "wet"
+ },
+ {
+ "id": "bread",
+ "nameKey": "item.bread",
+ "categoryId": "wet"
+ },
+ {
+ "id": "banana",
+ "nameKey": "item.banana",
+ "categoryId": "wet"
+ },
+ {
+ "id": "tea-residue",
+ "nameKey": "item.teaResidue",
+ "categoryId": "wet"
+ },
+ {
+ "id": "plastic-bag",
+ "nameKey": "item.plasticBag",
+ "categoryId": "dry"
+ },
+ {
+ "id": "zongzi-leaf",
+ "nameKey": "item.zongziLeaf",
+ "categoryId": "dry"
+ },
+ {
+ "id": "walnut-shell",
+ "nameKey": "item.walnutShell",
+ "categoryId": "dry"
+ },
+ {
+ "id": "hair",
+ "nameKey": "item.hair",
+ "categoryId": "dry"
+ },
+ {
+ "id": "shell",
+ "nameKey": "item.shell",
+ "categoryId": "dry"
+ },
+ {
+ "id": "sanitary-pad",
+ "nameKey": "item.sanitaryPad",
+ "categoryId": "dry"
+ },
+ {
+ "id": "condom",
+ "nameKey": "item.condom",
+ "categoryId": "dry"
+ },
+ {
+ "id": "chewing-gum",
+ "nameKey": "item.chewingGum",
+ "categoryId": "dry"
+ },
+ {
+ "id": "lighter",
+ "nameKey": "item.lighter",
+ "categoryId": "dry"
+ },
+ {
+ "id": "coconut-shell",
+ "nameKey": "item.coconutShell",
+ "categoryId": "dry"
+ },
+ {
+ "id": "cat-litter",
+ "nameKey": "item.catLitter",
+ "categoryId": "dry"
+ },
+ {
+ "id": "face-mask",
+ "nameKey": "item.faceMask",
+ "categoryId": "dry"
+ },
+ {
+ "id": "tissue",
+ "nameKey": "item.tissue",
+ "categoryId": "dry"
+ },
+ {
+ "id": "big-bone",
+ "nameKey": "item.bigBone",
+ "categoryId": "dry"
+ },
+ {
+ "id": "milk-tea-cup",
+ "nameKey": "item.milkTeaCup",
+ "categoryId": "dry"
+ },
+ {
+ "id": "paper-towel",
+ "nameKey": "item.paperTowel",
+ "categoryId": "dry"
+ },
+ {
+ "id": "clam-shell",
+ "nameKey": "item.clamShell",
+ "categoryId": "dry"
+ },
+ {
+ "id": "zongzi-leaf2",
+ "nameKey": "item.zongziLeaf2",
+ "categoryId": "dry"
+ },
+ {
+ "id": "corn-husk",
+ "nameKey": "item.cornHusk",
+ "categoryId": "dry"
+ },
+ {
+ "id": "straw",
+ "nameKey": "item.straw",
+ "categoryId": "dry"
+ },
+ {
+ "id": "tea-bag",
+ "nameKey": "item.teaBag",
+ "categoryId": "dry"
+ },
+ {
+ "id": "sugarcane-peel",
+ "nameKey": "item.sugarcanePeel",
+ "categoryId": "dry"
+ },
+ {
+ "id": "desiccant",
+ "nameKey": "item.desiccant",
+ "categoryId": "dry"
+ },
+ {
+ "id": "disposable-chopsticks",
+ "nameKey": "item.disposableChopsticks",
+ "categoryId": "dry"
+ },
+ {
+ "id": "corn-shell",
+ "nameKey": "item.cornShell",
+ "categoryId": "dry"
+ },
+ {
+ "id": "cigarette",
+ "nameKey": "item.cigarette",
+ "categoryId": "dry"
+ },
+ {
+ "id": "wet-wipe",
+ "nameKey": "item.wetWipe",
+ "categoryId": "dry"
+ },
+ {
+ "id": "durian-shell",
+ "nameKey": "item.durianShell",
+ "categoryId": "dry"
+ },
+ {
+ "id": "toilet-paper",
+ "nameKey": "item.toiletPaper",
+ "categoryId": "dry"
+ },
+ {
+ "id": "big-walnut-shell",
+ "nameKey": "item.bigWalnutShell",
+ "categoryId": "dry"
+ },
+ {
+ "id": "nail",
+ "nameKey": "item.nail",
+ "categoryId": "dry"
+ },
+ {
+ "id": "packaging-bag",
+ "nameKey": "item.packagingBag",
+ "categoryId": "dry"
+ },
+ {
+ "id": "lipstick",
+ "nameKey": "item.lipstick",
+ "categoryId": "dry"
+ },
+ {
+ "id": "disposable-cup",
+ "nameKey": "item.disposableCup",
+ "categoryId": "dry"
+ },
+ {
+ "id": "snail-shell",
+ "nameKey": "item.snailShell",
+ "categoryId": "dry"
+ },
+ {
+ "id": "toothbrush",
+ "nameKey": "item.toothbrush",
+ "categoryId": "dry"
+ },
+ {
+ "id": "takeout-box",
+ "nameKey": "item.takeoutBox",
+ "categoryId": "dry"
+ },
+ {
+ "id": "durian",
+ "nameKey": "item.durian",
+ "categoryId": "dry"
+ },
+ {
+ "id": "diaper",
+ "nameKey": "item.diaper",
+ "categoryId": "dry"
+ },
+ {
+ "id": "trash-bag",
+ "nameKey": "item.trashBag",
+ "categoryId": "dry"
+ },
+ {
+ "id": "toothpaste-tube",
+ "nameKey": "item.toothpasteTube",
+ "categoryId": "dry"
+ },
+ {
+ "id": "ice-pack",
+ "nameKey": "item.icePack",
+ "categoryId": "dry"
+ },
+ {
+ "id": "sock",
+ "nameKey": "item.sock",
+ "categoryId": "dry"
+ },
+ {
+ "id": "pen",
+ "nameKey": "item.pen",
+ "categoryId": "dry"
+ },
+ {
+ "id": "diaper2",
+ "nameKey": "item.diaper2",
+ "categoryId": "dry"
+ },
+ {
+ "id": "durian-pit",
+ "nameKey": "item.durianPit",
+ "categoryId": "dry"
+ },
+ {
+ "id": "disposable-lunch-box",
+ "nameKey": "item.disposableLunchBox",
+ "categoryId": "dry"
+ },
+ {
+ "id": "tea-bag2",
+ "nameKey": "item.teaBag2",
+ "categoryId": "dry"
+ },
+ {
+ "id": "mask",
+ "nameKey": "item.mask",
+ "categoryId": "dry"
+ },
+ {
+ "id": "underwear",
+ "nameKey": "item.underwear",
+ "categoryId": "dry"
+ },
+ {
+ "id": "towel",
+ "nameKey": "item.towel",
+ "categoryId": "dry"
+ },
+ {
+ "id": "diaper3",
+ "nameKey": "item.diaper3",
+ "categoryId": "dry"
+ },
+ {
+ "id": "ceramic-bowl",
+ "nameKey": "item.ceramicBowl",
+ "categoryId": "dry"
+ },
+ {
+ "id": "pen-refill",
+ "nameKey": "item.penRefill",
+ "categoryId": "dry"
+ },
+ {
+ "id": "dirty-plastic-bag",
+ "nameKey": "item.dirtyPlasticBag",
+ "categoryId": "dry"
+ },
+ {
+ "id": "paper-clip",
+ "nameKey": "item.paperClip",
+ "categoryId": "dry"
+ },
+ {
+ "id": "toothpick",
+ "nameKey": "item.toothpick",
+ "categoryId": "dry"
+ },
+ {
+ "id": "food-packaging-bag",
+ "nameKey": "item.foodPackagingBag",
+ "categoryId": "dry"
+ },
+ {
+ "id": "watercolor-pen",
+ "nameKey": "item.watercolorPen",
+ "categoryId": "dry"
+ },
+ {
+ "id": "cotton-swab",
+ "nameKey": "item.cottonSwab",
+ "categoryId": "dry"
+ }
+]
diff --git a/css/styles.css b/css/styles.css
new file mode 100644
index 0000000..2346d40
--- /dev/null
+++ b/css/styles.css
@@ -0,0 +1,668 @@
+:root {
+ --color-recyclable: #104883;
+ --color-hazardous: #e53122;
+ --color-wet: #694539;
+ --color-dry: #312d2a;
+ --color-tab-inactive: #eceff3;
+ --color-tab-inactive-text: #9aa3b2;
+ --color-gray-bg: #f0f4f8;
+ --color-gray-text: #8a94a6;
+ --color-border: #e8ecf1;
+ --color-surface: #ffffff;
+ --color-body: #eef2f7;
+ --color-row-even: #ffffff;
+ --color-row-odd: #f5f8fb;
+ --radius-sm: 10px;
+ --radius-md: 14px;
+ --radius-lg: 18px;
+ --radius-xl: 22px;
+ --shadow-sm: 0 1px 3px rgba(15, 23, 42, 0.06);
+ --shadow-md: 0 4px 16px rgba(15, 23, 42, 0.08);
+ --shadow-lg: 0 12px 40px rgba(15, 23, 42, 0.14);
+}
+
+*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
+
+body {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
+ background: var(--color-body);
+ color: #2d3748;
+ line-height: 1.6;
+ -webkit-tap-highlight-color: transparent;
+}
+
+/* Layout utilities */
+.flex { display: flex; }
+.flex-col { flex-direction: column; }
+.flex-1 { flex: 1; }
+.items-center { align-items: center; }
+.items-start { align-items: flex-start; }
+.justify-center { justify-content: center; }
+.justify-between { justify-content: space-between; }
+.justify-end { justify-content: flex-end; }
+.gap-1 { gap: 0.25rem; }
+.gap-2 { gap: 0.5rem; }
+.gap-3 { gap: 0.75rem; }
+.w-full { width: 100%; }
+.h-full { height: 100%; }
+.min-h-screen { min-height: 100vh; }
+.max-w-md { max-width: 28rem; }
+.mx-auto { margin-left: auto; margin-right: auto; }
+.px-3 { padding-left: 0.75rem; padding-right: 0.75rem; }
+.px-4 { padding-left: 1rem; padding-right: 1rem; }
+.py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }
+.py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; }
+.py-4 { padding-top: 1rem; padding-bottom: 1rem; }
+.text-center { text-align: center; }
+.text-left { text-align: left; }
+.text-right { text-align: right; }
+.text-sm { font-size: 0.875rem; }
+.text-base { font-size: 1rem; }
+.text-lg { font-size: 1.125rem; }
+.font-bold { font-weight: 700; }
+.font-medium { font-weight: 500; }
+.rounded-lg { border-radius: var(--radius-md); }
+.shadow { box-shadow: var(--shadow-sm); }
+.shadow-lg { box-shadow: var(--shadow-lg); }
+.overflow-hidden { overflow: hidden; }
+.overflow-y-auto { overflow-y: auto; }
+.relative { position: relative; }
+.fixed { position: fixed; }
+.inset-0 { top: 0; right: 0; bottom: 0; left: 0; }
+.z-50 { z-index: 50; }
+.hidden { display: none !important; }
+.shrink-0 { flex-shrink: 0; }
+.cursor-pointer { cursor: pointer; }
+.select-none { user-select: none; }
+
+/* Category colors */
+.text-recyclable { color: var(--color-recyclable); }
+.text-hazardous { color: var(--color-hazardous); }
+.text-wet { color: var(--color-wet); }
+.text-dry { color: var(--color-dry); }
+.text-gray { color: var(--color-gray-text); }
+.bg-gray-light { background-color: var(--color-gray-bg); }
+
+/* App shell */
+.app-container {
+ max-width: 28rem;
+ margin: 0 auto;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ background: #eef2f7;
+ box-shadow: none;
+}
+
+/* Header */
+.header {
+ padding: 1.125rem 1.25rem 1rem;
+ background: #eef2f7;
+ border-bottom: none;
+ box-shadow: 0 1px 0 rgba(15, 23, 42, 0.05);
+}
+.header-top {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ margin-bottom: 0.875rem;
+ position: relative;
+}
+.header-actions {
+ display: flex;
+ align-items: center;
+ gap: 0.625rem;
+}
+.logo-icon {
+ /*width: 2.75rem; */
+ height: 2.75rem;
+ flex-shrink: 0;
+ position: absolute;
+ left: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ border-radius: var(--radius-sm);
+ box-shadow: var(--shadow-sm);
+}
+.title-text {
+ font-size: 1.2rem;
+ font-weight: 700;
+ line-height: 1.45;
+ color: #1a202c;
+ letter-spacing: -0.01em;
+}
+
+/* Buttons */
+.btn {
+ border: none;
+ cursor: pointer;
+ font-size: 0.875rem;
+ border-radius: var(--radius-sm);
+ transition: transform 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease;
+ font-family: inherit;
+}
+.btn:active { transform: scale(0.97); opacity: 0.9; }
+.btn-header {
+ padding: 0.5rem 0.875rem;
+ background: var(--color-gray-bg);
+ color: #4a5568;
+ font-weight: 500;
+ box-shadow: var(--shadow-sm);
+}
+.btn-query {
+ padding: 0.75rem 1.125rem;
+ background: linear-gradient(135deg, #1e5088 0%, #104883 100%);
+ color: #fff;
+ font-weight: 600;
+ white-space: nowrap;
+ box-shadow: 0 3px 10px rgba(23, 59, 107, 0.28);
+ border-radius: var(--radius-sm);
+}
+.btn-voice {
+ padding: 0.75rem 0.875rem;
+ background: var(--color-gray-bg);
+ color: #4a5568;
+ font-size: 0.75rem;
+ white-space: nowrap;
+ min-width: 4.75rem;
+ font-weight: 500;
+ box-shadow: var(--shadow-sm);
+ border-radius: var(--radius-sm);
+}
+.btn-voice.recording {
+ background: linear-gradient(135deg, #ff6b6b 0%, #ee4444 100%);
+ color: #fff;
+ animation: pulse 1.2s ease-in-out infinite;
+ box-shadow: 0 3px 12px rgba(238, 68, 68, 0.35);
+}
+.btn-standard {
+ padding: 0.375rem 0.875rem;
+ background: rgba(255, 255, 255, 0.92);
+ color: #2d3748;
+ font-size: 0.75rem;
+ font-weight: 600;
+ border-radius: 9999px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
+ backdrop-filter: blur(4px);
+}
+.btn-confirm {
+ width: 100%;
+ padding: 1rem 1.25rem;
+ background: linear-gradient(135deg, #1e5088 0%, #104883 100%);
+ color: #fff;
+ font-size: 1.0625rem;
+ font-weight: 600;
+ border-radius: var(--radius-md);
+ margin-top: 1.75rem;
+ box-shadow: 0 4px 14px rgba(23, 59, 107, 0.3);
+ letter-spacing: 0.02em;
+}
+.btn-close {
+ background: var(--color-gray-bg);
+ border: none;
+ font-size: 1.25rem;
+ color: #718096;
+ cursor: pointer;
+ line-height: 1;
+ width: 2rem;
+ height: 2rem;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: background 0.15s ease;
+}
+.btn-close:hover { background: #e2e8f0; }
+.btn-close-transparent {
+ background: transparent;
+ border: none;
+ font-size: 1.75rem;
+ color: rgba(0, 0, 0, 0.22);
+ cursor: pointer;
+ line-height: 1;
+ padding: 0.625rem;
+ margin-top: 0.75rem;
+ border-radius: 50%;
+ transition: color 0.15s ease, background 0.15s ease;
+}
+.btn-close-transparent:hover {
+ color: rgba(0, 0, 0, 0.45);
+ background: var(--color-gray-bg);
+}
+
+@keyframes pulse {
+ 0%, 100% { opacity: 1; transform: scale(1); }
+ 50% { opacity: 0.85; transform: scale(0.98); }
+}
+
+/* Search row */
+.search-row {
+ display: flex;
+ align-items: center;
+ gap: 0.625rem;
+ padding: 0.875rem 1.25rem 1rem;
+ background: #eef2f7;
+}
+.search-input {
+ flex: 1;
+ padding: 0.8125rem 1rem;
+ border: 1.5px solid var(--color-border);
+ border-radius: var(--radius-sm);
+ font-size: 1rem;
+ outline: none;
+ background: var(--color-gray-bg);
+ color: #2d3748;
+ transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
+}
+.search-input:focus {
+ border-color: var(--color-recyclable);
+ background: #fff;
+ box-shadow: 0 0 0 3px rgba(23, 59, 107, 0.12);
+}
+.search-input::placeholder {
+ color: #a0aec0;
+}
+
+/* Language dropdown */
+.lang-dropdown { position: relative; }
+.lang-menu {
+ position: absolute;
+ top: calc(100% + 6px);
+ right: 0;
+ background: #fff;
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-sm);
+ box-shadow: var(--shadow-lg);
+ min-width: 7rem;
+ z-index: 60;
+ overflow: hidden;
+ padding: 0.375rem;
+}
+.lang-menu-item {
+ padding: 0.625rem 0.875rem;
+ cursor: pointer;
+ font-size: 0.875rem;
+ border-radius: 8px;
+ color: #4a5568;
+ transition: background 0.15s ease;
+}
+.lang-menu-item:hover,
+.lang-menu-item.active {
+ background: var(--color-gray-bg);
+ color: #1a202c;
+ font-weight: 500;
+}
+
+/* Browse section */
+.browse-section {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ padding: 0 1rem 1rem;
+ gap: 0;
+}
+
+/* Tabs */
+.tabs-wrap {
+ border-radius: var(--radius-md);
+ overflow: hidden;
+ box-shadow: var(--shadow-sm);
+}
+.tabs {
+ display: flex;
+ gap: 0;
+ background: var(--color-tab-inactive);
+ padding: 0;
+}
+.tab {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ padding: 0;
+ cursor: pointer;
+ transition: background-color 0.2s ease;
+ border-radius: 0;
+ border-bottom: none;
+ background: var(--color-tab-inactive);
+ overflow: hidden;
+ min-width: 0;
+}
+.tab-color-bar {
+ display: block;
+ width: 100%;
+ height: 4px;
+ flex-shrink: 0;
+}
+.tab.active {
+ position: relative;
+ z-index: 1;
+ margin-bottom: -1px;
+}
+.tab-icon {
+ display: block;
+ width: 100%;
+ max-width: 210px;
+ height: auto;
+ aspect-ratio: 1 / 1;
+ margin: 0 auto;
+ object-fit: contain;
+ object-position: center;
+}
+.tab.active .tab-icon {
+ filter: none;
+}
+
+/* Tab detail */
+.tab-detail {
+ padding: 1rem 1.125rem 1.125rem;
+ color: #fff;
+ display: flex;
+ flex-direction: column;
+ min-height: 4.5rem;
+ border-radius: 0;
+ box-shadow: none;
+ margin-top: -1px;
+}
+.tab-desc {
+ font-size: 0.875rem;
+ line-height: 1.65;
+ opacity: 0.95;
+}
+.tab-standard-wrap {
+ align-self: flex-end;
+ margin-top: calc(1 * 1.65em);
+}
+
+/* Search result hints */
+.search-hints {
+ padding: 1rem 1.25rem;
+ background: var(--color-gray-bg);
+ border-radius: var(--radius-md);
+ margin: 0 1rem 0.75rem;
+}
+.search-hint-main {
+ font-size: 0.9375rem;
+ font-weight: 600;
+ margin-bottom: 0.375rem;
+ color: #2d3748;
+ line-height: 1.5;
+}
+.search-hint-sub {
+ font-size: 0.8125rem;
+ color: var(--color-gray-text);
+ line-height: 1.5;
+}
+
+/* Item list */
+.item-list {
+ flex: 1;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+}
+.item-list-browse {
+ margin-top: 0.875rem;
+ border-radius: var(--radius-md);
+ overflow: hidden;
+ border: 1px solid var(--color-border);
+ box-shadow: var(--shadow-sm);
+}
+.item-list-search-wrap {
+ margin: 0 1rem 1rem;
+ border-radius: var(--radius-md);
+ overflow: hidden;
+ border: 1px solid var(--color-border);
+ box-shadow: var(--shadow-sm);
+}
+.list-item {
+ padding: 1rem 1.125rem;
+ text-align: center;
+ cursor: pointer;
+ font-size: 1rem;
+ color: #2d3748;
+ transition: background 0.15s ease;
+ letter-spacing: 0.01em;
+}
+.list-item-even {
+ background: var(--color-row-even);
+}
+.list-item-odd {
+ background: var(--color-row-odd);
+}
+.list-item:active {
+ background: #e8f0fe !important;
+}
+.list-item-search {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ text-align: left;
+ padding: 1rem 1.25rem;
+}
+.list-item-search .item-name {
+ flex: 1;
+ font-weight: 500;
+}
+.list-item-search .item-category {
+ font-size: 0.875rem;
+ font-weight: 600;
+ flex-shrink: 0;
+ margin-left: 0.75rem;
+}
+
+/* Modals */
+.modal-overlay {
+ position: fixed;
+ inset: 0;
+ background: rgba(15, 23, 42, 0.45);
+ backdrop-filter: blur(4px);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 50;
+ padding: 1.25rem;
+ animation: fadeIn 0.2s ease;
+}
+.modal-card {
+ background: #fff;
+ border-radius: var(--radius-xl);
+ padding: 1.75rem 1.625rem;
+ width: 100%;
+ max-width: 22rem;
+ max-height: 85vh;
+ overflow-y: auto;
+ position: relative;
+ box-shadow: var(--shadow-lg);
+ animation: slideUp 0.25s ease;
+}
+.modal-card-wide {
+ max-width: 24rem;
+}
+.modal-card-item {
+ color: #fff;
+}
+.modal-card-item .modal-title {
+ color: #fff;
+}
+.modal-card-item .modal-line {
+ color: #fff;
+ opacity: 0.95;
+}
+.modal-card-item .modal-divider {
+ border-top-color: rgba(255, 255, 255, 0.35);
+}
+.modal-card-item .modal-tips-title {
+ color: #fff;
+}
+.modal-card-item .modal-tips-list {
+ color: #fff;
+ opacity: 0.9;
+}
+.modal-card-item .modal-standard-body {
+ color: #fff;
+ opacity: 0.95;
+}
+.modal-card-item .btn-close-transparent {
+ color: rgba(255, 255, 255, 0.55);
+}
+.modal-card-item .btn-close-transparent:hover {
+ color: rgba(255, 255, 255, 0.9);
+ background: rgba(255, 255, 255, 0.12);
+}
+.modal-header {
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: 0.25rem;
+}
+.modal-title {
+ font-size: 1.3125rem;
+ font-weight: 700;
+ text-align: center;
+ margin-bottom: 1rem;
+ color: #1a202c;
+ line-height: 1.35;
+}
+.modal-suggest {
+ text-align: center;
+ color: #fff;
+}
+.modal-suggest-label {
+ font-size: 0.875rem;
+ color: #fff;
+ opacity: 0.95;
+ line-height: 1.65;
+}
+.modal-suggest-visual {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+.modal-suggest-icon {
+ display: block;
+ width: auto;
+ max-width: 210px;
+ height: auto;
+ aspect-ratio: 1 / 1;
+ object-fit: contain;
+ object-position: center;
+}
+.modal-line {
+ font-size: 0.875rem;
+ color: #4a5568;
+ margin-bottom: 0.5rem;
+ line-height: 1.65;
+ padding: 0 0.5rem;
+}
+.modal-divider {
+ border: none;
+ border-top: 1px solid var(--color-border);
+ margin: 1.25rem 0 1rem;
+}
+.modal-tips-title {
+ font-size: 0.875rem;
+ font-weight: 700;
+ margin-bottom: 0.625rem;
+ color: #2d3748;
+}
+.modal-tips-list {
+ font-size: 0.8125rem;
+ color: #718096;
+ line-height: 1.85;
+ padding-left: 0;
+ list-style: none;
+}
+.modal-tips-list li {
+ margin-bottom: 0.375rem;
+ padding-left: 0.25rem;
+}
+.modal-standard-body {
+ font-size: 0.875rem;
+ line-height: 1.75;
+ color: #4a5568;
+ white-space: pre-line;
+ padding: 0 0.25rem;
+}
+.welcome-title {
+ font-size: 1.375rem;
+ font-weight: 700;
+ text-align: center;
+ color: #1a202c;
+ line-height: 1.35;
+ margin-bottom: 1.25rem;
+}
+.welcome-text p {
+ font-size: 0.9375rem;
+ line-height: 1.75;
+ margin-bottom: 0.875rem;
+ text-align: left;
+ color: #4a5568;
+}
+.welcome-text p:last-child {
+ margin-bottom: 0;
+}
+
+@keyframes fadeIn {
+ from { opacity: 0; }
+ to { opacity: 1; }
+}
+@keyframes slideUp {
+ from { opacity: 0; transform: translateY(12px); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+/* Main content area */
+.main-content {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ background: var(--color-body);
+}
+
+#browse-view {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+}
+
+#search-view {
+ padding-top: 0.75rem;
+}
+
+.no-results {
+ padding: 2.5rem 1.5rem;
+ text-align: center;
+ color: var(--color-gray-text);
+ font-size: 0.9375rem;
+ line-height: 1.6;
+}
+
+.app-footer {
+ padding: 1rem 1.25rem 1.25rem;
+ text-align: center;
+ background: #eef2f7;
+ border-top: 1px solid var(--color-border);
+ flex-shrink: 0;
+}
+.app-footer p {
+ font-size: 0.75rem;
+ color: var(--color-gray-text);
+ line-height: 1.5;
+ letter-spacing: 0.01em;
+}
+
+@media (min-width: 768px) {
+ body {
+ padding: 1.5rem 0;
+ }
+ .app-container {
+ min-height: calc(100vh - 3rem);
+ border-radius: var(--radius-xl);
+ overflow: hidden;
+ }
+ .title-text { font-size: 1.375rem; }
+ .modal-card { max-width: 26rem; padding: 2rem 1.75rem; }
+ .list-item { padding: 1.0625rem 1.25rem; }
+}
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..5ac606f
--- /dev/null
+++ b/index.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
+ <title data-i18n="page.title"></title>
+ <link rel="stylesheet" href="css/styles.css">
+ <script charset="UTF-8" id="LA_COLLECT" src="//sdk.51.la/js-sdk-pro.min.js"></script>
+ <script>LA.init({ id: "3QXRnnbLfuoKqmdc", ck: "3QXRnnbLfuoKqmdc" })</script>
+</head>
+
+<body>
+ <div class="app-container">
+ <!-- Header -->
+ <header class="header">
+ <div class="header-top">
+ <img src="assets/logo.png" alt="" class="logo-icon" id="logo">
+ <div class="header-actions">
+ <button type="button" class="btn btn-header hidden" id="btn-home" data-i18n="btn.home"></button>
+ <div class="lang-dropdown" id="lang-dropdown">
+ <button type="button" class="btn btn-header" id="btn-lang"></button>
+ <div class="lang-menu hidden" id="lang-menu"></div>
+ </div>
+ </div>
+ </div>
+ <h1 class="title-text" data-i18n="header.title"></h1>
+ </header>
+
+ <!-- Search -->
+ <div class="search-row">
+ <input type="text" class="search-input" id="search-input" data-i18n-placeholder="search.placeholder">
+ <button type="button" class="btn btn-query" id="btn-query" data-i18n="btn.query"></button>
+ <button type="button" class="btn btn-voice" id="btn-voice" data-i18n="btn.voice"></button>
+ </div>
+
+ <!-- Main content -->
+ <div class="main-content" id="main-content">
+ <!-- Browse mode -->
+ <div id="browse-view">
+ <div class="browse-section">
+ <div class="tabs-wrap">
+ <div class="tabs" id="tabs"></div>
+ <div class="tab-detail" id="tab-detail">
+ <p class="tab-desc" id="tab-desc"></p>
+ <div class="tab-standard-wrap">
+ <button type="button" class="btn btn-standard" id="btn-standard" data-i18n="btn.standard"></button>
+ </div>
+ </div>
+ </div>
+ <div class="item-list item-list-browse" id="item-list"></div>
+ </div>
+ </div>
+
+ <!-- Search fuzzy results -->
+ <div id="search-view" class="hidden flex flex-col h-full">
+ <div class="search-hints">
+ <p class="search-hint-main" data-i18n="search.notFoundHint"></p>
+ <p class="search-hint-sub" data-i18n="search.referenceHint"></p>
+ </div>
+ <div class="item-list flex-1" id="search-results"></div>
+ </div>
+
+ <div class="no-results hidden" id="no-results" data-i18n="search.noResults"></div>
+ </div>
+
+ <footer class="app-footer">
+ <p data-i18n="footer.copyright"></p>
+ </footer>
+ </div>
+
+ <!-- Welcome modal -->
+ <div class="modal-overlay hidden" id="welcome-modal">
+ <div class="modal-card">
+ <h2 class="welcome-title" data-i18n="welcome.title"></h2>
+ <div class="welcome-text">
+ <p data-i18n="welcome.p1"></p>
+ <p data-i18n="welcome.p2"></p>
+ <p data-i18n="welcome.p3"></p>
+ </div>
+ <button type="button" class="btn btn-confirm" id="btn-welcome-confirm" data-i18n="welcome.confirm"></button>
+ </div>
+ </div>
+
+ <!-- Standard modal -->
+ <div class="modal-overlay hidden" id="standard-modal">
+ <div class="modal-card modal-card-wide modal-card-item" id="standard-modal-card">
+ <h2 class="modal-title" id="standard-title"></h2>
+ <div class="modal-standard-body" id="standard-body"></div>
+ <div class="text-center">
+ <button type="button" class="btn-close-transparent" id="btn-standard-close" aria-label="close">×</button>
+ </div>
+ </div>
+ </div>
+
+ <!-- Item disposal modal -->
+ <div class="modal-overlay hidden" id="item-modal">
+ <div class="modal-card modal-card-item" id="item-modal-card">
+ <h2 class="modal-title" id="item-modal-name"></h2>
+ <div class="modal-suggest" id="item-modal-suggest">
+ <p class="modal-suggest-label" data-i18n="disposal.suggestLabel"></p>
+ <div class="modal-suggest-visual">
+ <img src="" alt="" class="modal-suggest-icon" id="item-modal-icon" width="180" height="180">
+ </div>
+ </div>
+ <p class="modal-line" id="item-modal-line1"></p>
+ <p class="modal-line" id="item-modal-line2"></p>
+ <hr class="modal-divider">
+ <p class="modal-tips-title" data-i18n="disposal.tipsTitle"></p>
+ <ol class="modal-tips-list" id="item-modal-tips"></ol>
+ <div class="text-center">
+ <button type="button" class="btn-close-transparent" id="btn-item-close" aria-label="close">×</button>
+ </div>
+ </div>
+ </div>
+
+ <script src="js/storage.js"></script>
+ <script src="js/i18n.js"></script>
+ <script src="js/data.js"></script>
+ <script src="js/app.js"></script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/js/app.js b/js/app.js
new file mode 100644
index 0000000..1f4c9d9
--- /dev/null
+++ b/js/app.js
@@ -0,0 +1,353 @@
+const App = {
+ state: 'home',
+ currentCategoryId: 'recyclable',
+ recognition: null,
+ isRecording: false,
+ longPressTimer: null,
+ longPressDelay: 300,
+
+ els: {},
+
+ async init() {
+ this.cacheElements();
+ await I18n.load('zh');
+ await DataStore.load();
+ I18n.applyToDOM();
+ this.initLangDropdown();
+ this.renderTabs();
+ this.selectCategory('recyclable');
+ this.bindEvents();
+ this.initVoice();
+ this.showWelcomeIfNeeded();
+ history.replaceState({ view: 'home' }, '');
+ },
+
+ cacheElements() {
+ this.els.searchInput = document.getElementById('search-input');
+ this.els.btnQuery = document.getElementById('btn-query');
+ this.els.btnVoice = document.getElementById('btn-voice');
+ this.els.btnHome = document.getElementById('btn-home');
+ this.els.btnLang = document.getElementById('btn-lang');
+ this.els.langMenu = document.getElementById('lang-menu');
+ this.els.langDropdown = document.getElementById('lang-dropdown');
+ this.els.tabs = document.getElementById('tabs');
+ this.els.tabDetail = document.getElementById('tab-detail');
+ this.els.tabDesc = document.getElementById('tab-desc');
+ this.els.btnStandard = document.getElementById('btn-standard');
+ this.els.itemList = document.getElementById('item-list');
+ this.els.browseView = document.getElementById('browse-view');
+ this.els.searchView = document.getElementById('search-view');
+ this.els.searchResults = document.getElementById('search-results');
+ this.els.welcomeModal = document.getElementById('welcome-modal');
+ this.els.btnWelcomeConfirm = document.getElementById('btn-welcome-confirm');
+ this.els.standardModal = document.getElementById('standard-modal');
+ this.els.standardModalCard = document.getElementById('standard-modal-card');
+ this.els.btnStandardClose = document.getElementById('btn-standard-close');
+ this.els.standardTitle = document.getElementById('standard-title');
+ this.els.standardBody = document.getElementById('standard-body');
+ this.els.itemModal = document.getElementById('item-modal');
+ this.els.itemModalCard = document.getElementById('item-modal-card');
+ this.els.itemModalSuggest = document.getElementById('item-modal-suggest');
+ this.els.itemModalName = document.getElementById('item-modal-name');
+ this.els.itemModalIcon = document.getElementById('item-modal-icon');
+ this.els.itemModalLine1 = document.getElementById('item-modal-line1');
+ this.els.itemModalLine2 = document.getElementById('item-modal-line2');
+ this.els.itemModalTips = document.getElementById('item-modal-tips');
+ this.els.btnItemClose = document.getElementById('btn-item-close');
+ this.els.noResults = document.getElementById('no-results');
+ },
+
+ initLangDropdown() {
+ const current = I18n.languages.find(l => l.code === I18n.currentLang);
+ this.els.btnLang.textContent = I18n.t(current.labelKey);
+ const onLangSelect = async (code) => {
+ await I18n.load(code);
+ I18n.applyToDOM();
+ this.els.btnLang.textContent = I18n.t(I18n.languages.find(l => l.code === code).labelKey);
+ I18n.renderLangMenu(this.els.langMenu, onLangSelect);
+ this.els.langMenu.classList.add('hidden');
+ this.renderTabs();
+ this.selectCategory(this.currentCategoryId);
+ if (this.state === 'searchFuzzy') {
+ const q = this.els.searchInput.value.trim();
+ if (q) this.search(q, false);
+ }
+ };
+ I18n.renderLangMenu(this.els.langMenu, onLangSelect);
+ },
+
+ bindEvents() {
+ this.els.btnQuery.addEventListener('click', () => {
+ const q = this.els.searchInput.value.trim();
+ if (q) this.search(q);
+ });
+ this.els.searchInput.addEventListener('keydown', (e) => {
+ if (e.key === 'Enter') {
+ const q = this.els.searchInput.value.trim();
+ if (q) this.search(q);
+ }
+ });
+ this.els.btnHome.addEventListener('click', () => this.goHome());
+ this.els.btnLang.addEventListener('click', (e) => {
+ e.stopPropagation();
+ this.els.langMenu.classList.toggle('hidden');
+ });
+ document.addEventListener('click', () => {
+ this.els.langMenu.classList.add('hidden');
+ });
+ this.els.btnStandard.addEventListener('click', () => this.openStandardModal());
+ this.els.btnStandardClose.addEventListener('click', () => this.closeStandardModal());
+ this.els.standardModal.addEventListener('click', (e) => {
+ if (e.target === this.els.standardModal) this.closeStandardModal();
+ });
+ this.els.btnItemClose.addEventListener('click', () => this.closeItemModal());
+ this.els.itemModal.addEventListener('click', (e) => {
+ if (e.target === this.els.itemModal) this.closeItemModal();
+ });
+ this.els.btnWelcomeConfirm.addEventListener('click', () => {
+ Storage.dismissWelcome();
+ this.els.welcomeModal.classList.add('hidden');
+ });
+ window.addEventListener('popstate', (e) => {
+ if (!e.state || e.state.view === 'home') {
+ this.goHome(false);
+ }
+ });
+ },
+
+ showWelcomeIfNeeded() {
+ if (!Storage.isWelcomeDismissed()) {
+ this.els.welcomeModal.classList.remove('hidden');
+ }
+ },
+
+ renderTabs() {
+ this.els.tabs.innerHTML = '';
+ DataStore.categories.forEach(cat => {
+ const tab = document.createElement('div');
+ tab.className = 'tab';
+ tab.dataset.categoryId = cat.id;
+ tab.innerHTML =
+ '<span class="tab-color-bar" style="background-color:' + cat.color + '"></span>' +
+ '<img src="' + (cat.iconInactive || cat.icon) + '" alt="" class="tab-icon" width="210" height="210">';
+ tab.addEventListener('click', () => {
+ if (this.state === 'searchFuzzy') return;
+ this.selectCategory(cat.id);
+ });
+ this.els.tabs.appendChild(tab);
+ });
+ },
+
+ updateTabStates(categoryId) {
+ this.els.tabs.querySelectorAll('.tab').forEach(tab => {
+ const cat = DataStore.getCategory(tab.dataset.categoryId);
+ if (!cat) return;
+ const isActive = tab.dataset.categoryId === categoryId;
+ tab.classList.toggle('active', isActive);
+ tab.style.backgroundColor = isActive ? cat.color : '';
+ const iconEl = tab.querySelector('.tab-icon');
+ if (iconEl) {
+ iconEl.src = isActive ? cat.icon : (cat.iconInactive || cat.icon);
+ }
+ });
+ },
+
+ selectCategory(categoryId) {
+ this.currentCategoryId = categoryId;
+ const cat = DataStore.getCategory(categoryId);
+ if (!cat) return;
+
+ this.updateTabStates(categoryId);
+ this.els.tabDetail.style.backgroundColor = cat.color;
+ this.els.tabDesc.textContent = I18n.t(cat.descKey);
+ this.renderItemList(DataStore.getItemsByCategory(categoryId), this.els.itemList, false);
+ },
+
+ renderItemList(items, container, isSearch) {
+ container.innerHTML = '';
+ container.classList.toggle('item-list-browse', !isSearch);
+ container.classList.toggle('item-list-search-wrap', isSearch);
+ items.forEach((item, index) => {
+ const row = document.createElement('div');
+ if (isSearch) {
+ row.className = 'list-item list-item-search' + (index % 2 === 0 ? ' list-item-even' : ' list-item-odd');
+ const cat = DataStore.getCategory(item.categoryId);
+ row.innerHTML =
+ '<span class="item-name">' + DataStore.getLocalizedName(item) + '</span>' +
+ '<span class="item-category ' + DataStore.getCategoryColorClass(item.categoryId) + '">' +
+ I18n.t(cat.nameKey) + '</span>';
+ } else {
+ row.className = 'list-item' + (index % 2 === 0 ? ' list-item-even' : ' list-item-odd');
+ row.textContent = DataStore.getLocalizedName(item);
+ }
+ row.addEventListener('click', () => this.openItemModal(item));
+ container.appendChild(row);
+ });
+ },
+
+ openStandardModal() {
+ const cat = DataStore.getCategory(this.currentCategoryId);
+ if (!cat) return;
+ this.els.standardModalCard.style.backgroundColor = cat.color;
+ this.els.standardTitle.textContent = I18n.t(cat.nameKey) + ' - ' + I18n.t('btn.standard');
+ this.els.standardBody.textContent = I18n.t(cat.standardKey);
+ this.els.standardModal.classList.remove('hidden');
+ },
+
+ closeStandardModal() {
+ this.els.standardModal.classList.add('hidden');
+ },
+
+ openItemModal(item) {
+ const cat = DataStore.getCategory(item.categoryId);
+ if (!cat) return;
+ const tpl = cat.disposalTemplate;
+
+ this.els.itemModalName.textContent = DataStore.getLocalizedName(item);
+ this.els.itemModalCard.style.backgroundColor = cat.color;
+ this.els.itemModalIcon.src = cat.icon;
+ this.els.itemModalLine1.textContent = I18n.t(tpl.line1Key);
+ this.els.itemModalLine2.textContent = I18n.t(tpl.line2Key);
+
+ this.els.itemModalTips.innerHTML = '';
+ tpl.tipsKeys.forEach((key, i) => {
+ const li = document.createElement('li');
+ li.textContent = (i + 1) + '. ' + I18n.t(key);
+ this.els.itemModalTips.appendChild(li);
+ });
+
+ this.els.itemModal.classList.remove('hidden');
+ },
+
+ closeItemModal() {
+ this.els.itemModal.classList.add('hidden');
+ },
+
+ search(query, pushHistory) {
+ if (pushHistory === undefined) pushHistory = true;
+ const q = query.trim().toLowerCase();
+ if (!q) return;
+
+ this.els.noResults.classList.add('hidden');
+ const allItems = DataStore.getAllItemsLocalized();
+ const exact = allItems.filter(i => i.localName.toLowerCase() === q);
+
+ if (exact.length === 1) {
+ this.state = 'searchExact';
+ this.els.btnHome.classList.add('hidden');
+ this.openItemModal(exact[0]);
+ return;
+ }
+
+ const fuzzy = allItems.filter(i => i.localName.toLowerCase().includes(q));
+
+ if (fuzzy.length === 0) {
+ this.els.browseView.classList.remove('hidden');
+ this.els.searchView.classList.add('hidden');
+ this.els.btnHome.classList.add('hidden');
+ this.els.noResults.classList.remove('hidden');
+ this.state = 'home';
+ return;
+ }
+
+ this.state = 'searchFuzzy';
+ this.els.browseView.classList.add('hidden');
+ this.els.searchView.classList.remove('hidden');
+ this.els.btnHome.classList.remove('hidden');
+ this.renderItemList(fuzzy, this.els.searchResults, true);
+
+ if (pushHistory) {
+ if (this.state === 'searchFuzzy') {
+ history.replaceState({ view: 'search' }, '');
+ } else {
+ history.pushState({ view: 'search' }, '');
+ }
+ }
+ },
+
+ goHome(fromHistory) {
+ if (fromHistory === undefined) fromHistory = true;
+ this.state = 'home';
+ this.els.searchInput.value = '';
+ this.els.browseView.classList.remove('hidden');
+ this.els.searchView.classList.add('hidden');
+ this.els.btnHome.classList.add('hidden');
+ this.els.noResults.classList.add('hidden');
+ this.closeItemModal();
+ this.closeStandardModal();
+ this.selectCategory('recyclable');
+ if (fromHistory && history.state && history.state.view === 'search') {
+ history.back();
+ }
+ },
+
+ initVoice() {
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
+ if (!SpeechRecognition) {
+ this.els.btnVoice.classList.add('hidden');
+ return;
+ }
+
+ this.recognition = new SpeechRecognition();
+ this.recognition.lang = I18n.getLocale();
+ this.recognition.interimResults = false;
+ this.recognition.maxAlternatives = 1;
+
+ this.recognition.onresult = (event) => {
+ const transcript = event.results[0][0].transcript;
+ this.els.searchInput.value = transcript;
+ this.search(transcript);
+ };
+
+ this.recognition.onerror = () => {
+ this.stopRecording();
+ };
+
+ this.recognition.onend = () => {
+ this.stopRecording();
+ };
+
+ const startRecording = (e) => {
+ e.preventDefault();
+ this.longPressTimer = setTimeout(() => {
+ this.startRecording();
+ }, this.longPressDelay);
+ };
+
+ const cancelLongPress = () => {
+ if (this.longPressTimer) {
+ clearTimeout(this.longPressTimer);
+ this.longPressTimer = null;
+ }
+ if (this.isRecording) {
+ this.recognition.stop();
+ }
+ };
+
+ this.els.btnVoice.addEventListener('mousedown', startRecording);
+ this.els.btnVoice.addEventListener('mouseup', cancelLongPress);
+ this.els.btnVoice.addEventListener('mouseleave', cancelLongPress);
+ this.els.btnVoice.addEventListener('touchstart', startRecording, { passive: false });
+ this.els.btnVoice.addEventListener('touchend', cancelLongPress);
+ this.els.btnVoice.addEventListener('touchcancel', cancelLongPress);
+ },
+
+ startRecording() {
+ if (this.isRecording) return;
+ this.isRecording = true;
+ this.recognition.lang = I18n.getLocale();
+ this.els.btnVoice.classList.add('recording');
+ try {
+ this.recognition.start();
+ } catch {
+ this.stopRecording();
+ }
+ },
+
+ stopRecording() {
+ this.isRecording = false;
+ this.els.btnVoice.classList.remove('recording');
+ }
+};
+
+document.addEventListener('DOMContentLoaded', () => App.init());
diff --git a/js/data.js b/js/data.js
new file mode 100644
index 0000000..8860820
--- /dev/null
+++ b/js/data.js
@@ -0,0 +1,51 @@
+const DataStore = {
+ categories: [],
+ items: [],
+ categoryMap: {},
+
+ async load() {
+ const [catRes, itemRes] = await Promise.all([
+ fetch('config/categories.json'),
+ fetch('config/items.json')
+ ]);
+ this.categories = await catRes.json();
+ this.items = await itemRes.json();
+ this.categoryMap = {};
+ this.categories.forEach(c => { this.categoryMap[c.id] = c; });
+ },
+
+ getCategory(id) {
+ return this.categoryMap[id];
+ },
+
+ getItemsByCategory(categoryId) {
+ return this.items.filter(i => i.categoryId === categoryId);
+ },
+
+ getLocalizedName(item) {
+ return I18n.t(item.nameKey);
+ },
+
+ getAllItemsLocalized() {
+ return this.items.map(item => ({
+ ...item,
+ localName: this.getLocalizedName(item),
+ category: this.getCategory(item.categoryId)
+ }));
+ },
+
+ getCategoryName(categoryId) {
+ const cat = this.getCategory(categoryId);
+ return cat ? I18n.t(cat.nameKey) : '';
+ },
+
+ getCategoryColorClass(categoryId) {
+ const map = {
+ recyclable: 'text-recyclable',
+ hazardous: 'text-hazardous',
+ wet: 'text-wet',
+ dry: 'text-dry'
+ };
+ return map[categoryId] || '';
+ }
+};
diff --git a/js/i18n.js b/js/i18n.js
new file mode 100644
index 0000000..419782f
--- /dev/null
+++ b/js/i18n.js
@@ -0,0 +1,54 @@
+const I18n = {
+ currentLang: 'zh',
+ strings: {},
+ languages: [
+ { code: 'zh', labelKey: 'lang.zh', locale: 'zh-CN', file: 'config/i18n/zh.json' },
+ { code: 'en', labelKey: 'lang.en', locale: 'en-US', file: 'config/i18n/en.json' },
+ { code: 'ko', labelKey: 'lang.ko', locale: 'ko-KR', file: 'config/i18n/ko.json' },
+ { code: 'ja', labelKey: 'lang.ja', locale: 'ja-JP', file: 'config/i18n/ja.json' }
+ ],
+
+ async load(lang) {
+ const langConfig = this.languages.find(l => l.code === lang);
+ if (!langConfig) return;
+ const res = await fetch(langConfig.file);
+ this.strings = await res.json();
+ this.currentLang = lang;
+ document.documentElement.lang = langConfig.locale;
+ },
+
+ t(key) {
+ return this.strings[key] || key;
+ },
+
+ getLocale() {
+ const langConfig = this.languages.find(l => l.code === this.currentLang);
+ return langConfig ? langConfig.locale : 'zh-CN';
+ },
+
+ applyToDOM() {
+ document.querySelectorAll('[data-i18n]').forEach(el => {
+ const key = el.getAttribute('data-i18n');
+ el.textContent = this.t(key);
+ });
+ document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
+ const key = el.getAttribute('data-i18n-placeholder');
+ el.placeholder = this.t(key);
+ });
+ const titleEl = document.querySelector('title[data-i18n]');
+ if (titleEl) {
+ document.title = this.t(titleEl.getAttribute('data-i18n'));
+ }
+ },
+
+ renderLangMenu(menuEl, onSelect) {
+ menuEl.innerHTML = '';
+ this.languages.forEach(lang => {
+ const item = document.createElement('div');
+ item.className = 'lang-menu-item' + (lang.code === this.currentLang ? ' active' : '');
+ item.textContent = this.t(lang.labelKey);
+ item.addEventListener('click', () => onSelect(lang.code));
+ menuEl.appendChild(item);
+ });
+ }
+};
diff --git a/js/storage.js b/js/storage.js
new file mode 100644
index 0000000..d73e2ff
--- /dev/null
+++ b/js/storage.js
@@ -0,0 +1,22 @@
+const WELCOME_KEY = 'garbage_welcome_dismissed_at';
+const WELCOME_COOLDOWN_MS = 7 * 24 * 60 * 60 * 1000;
+
+const Storage = {
+ isWelcomeDismissed() {
+ try {
+ const dismissedAt = localStorage.getItem(WELCOME_KEY);
+ if (!dismissedAt) return false;
+ return Date.now() - parseInt(dismissedAt, 10) < WELCOME_COOLDOWN_MS;
+ } catch {
+ return false;
+ }
+ },
+
+ dismissWelcome() {
+ try {
+ localStorage.setItem(WELCOME_KEY, String(Date.now()));
+ } catch {
+ /* ignore */
+ }
+ }
+};
diff --git a/scripts/generate_items.py b/scripts/generate_items.py
new file mode 100644
index 0000000..d93218d
--- /dev/null
+++ b/scripts/generate_items.py
@@ -0,0 +1,417 @@
+# -*- coding: utf-8 -*-
+import json
+import os
+import re
+
+BASE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+RECYCLABLE = "鐗涘ザ鐩掋�佸鏂欍�佺幓鐠冪摱銆佺幓鐠冦�佺焊銆佽。鏈嶃�佺鐜荤拑銆佹槗鎷夌綈銆佸鏂欑洅銆佹场娌澘銆佸厖鐢靛疂銆侀瀷瀛愩�佺焊鐩掋�佹场娌銆佺幓鐠冩澂銆佹姤绾搞�佸鏂欐澂銆佺數绾裤�佹暟鎹嚎銆佺熆娉夋按鐡躲�佹灂澶淬�佸垁鐗囥�佽灪涓濄�佹场娌鏂欍�侀吀濂跺埄涔愬寘瑁呯洅銆佺焊琚嬨�佸寲濡嗗搧濉戞枡绌虹摱銆佺毊闉嬨�佸寲濡嗗搧鐜荤拑绌虹摱銆侀厭鐡躲�佸厖鐢电嚎銆佸箍鍛婂崟銆佸簾濉戞枡銆佺儫鐩掋�佸厖鐢靛櫒銆佷功鏈�佸暏閰掔摱銆佺焊鏉跨銆佹湪绛峰瓙銆佹瘺缁掔帺鍏枫�佽鍗曘�佸壀鍒�銆侀ギ鏂欏鏂欑摱銆佸竷銆侀櫎婀跨洅銆佸惛閾佺煶銆佸鏂欏寘瑁呯焊銆佽瀛愩�佸埄涔愬寘瑁呫�佺鐞冦�侀摑绠斻�佹彃搴с�侀搧銆侀挜鍖欍�佹墦鍗扮焊銆侀噾灞炪�佺櫧绾搞�佸寘瑁呯焊鐩掋�佸鏂欑洊銆佷俊灏�".split("銆�")
+
+HAZARDOUS = "鑽搧鍖呰銆佽嵂鐡躲�佺伅娉°�佹补婕嗘《銆佽嵂鍝併�佽繃鏈熻嵂銆佸厖鐢电數姹犮�佹寚鐢叉补銆佽搫鐢垫睜銆佺┖鑽摱銆佹湁瀹冲瀮鍦俱�佽繃鏈熻嵂鍝併�佸簾鑽搧銆佺伅绠°�佽崸鍏夌伅绠°�侀晬闀夌數姹犮�佺収鐗囥�佽崸鍏夌伅銆佹煋鍙戝墏澹炽�佺溂鑽按銆佽妭鑳界伅銆佹潃铏墏銆佽嵂鐗囥�佽嵂鐗囩洅銆佸彛鏈嶆恫鑽摱銆佸簾鑽摱銆佹补婕嗐�佺航鎵g數姹犮�侀伩瀛曡嵂銆佺溂鑽按鐡躲�佽兌鐗囥�佽兌鍥娿�佹按閾舵俯搴﹁銆佽�侀紶鑽�佽兌鍥婅嵂鐗囧簳鏉裤�佹煋鍙戝墏缃愩�佽妭鑳界伅娉°�佸悇绫昏繃鏈熻嵂鍝併�佺櫧鐐界伅娉°�佹墜鏈虹數姹犮�佹秷姣掓恫鐡躲�佽繃鏈熻嵂鐗囥�佹劅鍐掕嵂銆�84娑堟瘨娑茬┖鐡躲�佹寚鐢叉补鐡躲�佹潃姣掑柗闆剧綈銆佺浉鐗囧簳鐗囥�佷腑鎴愯嵂銆佽兌鍗枫�佽嵂鍝佸3瀛愩�佹按閾躲�佺浉鐗囥�佸簾娌规紗妗躲�佽繃鏈熻嵂鐗┿�佽嵂鍝侀摑濉戞澘銆佽煈铻傝嵂銆佽煈铻備父銆佽兌鍥婅嵂鐗囥�佹秷姣掕嵂鐗囥�佽妭鑳界伅绠�".split("銆�")
+
+WET = "鐡滃瓙澹炽�侀浮铔嬪3銆佺帀绫虫銆佽泲澹炽�佺帀绫炽�佹牳妗冦�佽姳鐢熷3銆佽尪鍙躲�侀緳铏惧3銆佸皬榫欒櫨銆佽煿澹炽�侀浮楠ㄥご銆佺摐瀛愩�佽瀮锜瑰3銆佺啛鐜夌背妫掋�佸紑蹇冩灉澹炽�佸皬榫欒櫨澹炽�佹瘺璞嗗3銆侀湠澹炽�侀钑夌毊銆佽タ鐡滅毊銆佹牀瀛愬3銆侀奔楠ㄥご銆侀緳铏俱�佺帀绫宠姱銆佺摐瀛愮墖銆佽姳銆佸挅鍟℃福銆佹帓楠ㄣ�佺步瀛愩�佷腑鑽福銆侀浮铔嬨�佽瀮锜广�佽崝鏋濆3銆佹瀛愩�佽瘽姊呮牳銆佹灒鏍搞�侀浮楠ㄣ�佽繃鏈熼鍝併�侀奔楠ㄣ�佽嫻鏋溿�佽崝鏋濇牳銆佹潹姊呫�佽タ鐡滅苯銆佹澘鏍楀3銆佽煈铻傘�佹灉鐨�佽姃鏋滄牳銆佽姳鐢熴�佸共鑺辩敓澹炽�侀ゼ骞层�佽タ鐡溿�侀矞鑺便�佺孩鏋f牳銆佽姦绋枫�佽嫻鏋滄牳銆佽尛鐧界毊銆侀潰鍖呫�侀钑夈�佽尪鍙舵福".split("銆�")
+
+DRY = "濉戞枡琚嬨�佺步鍙躲�佹牳妗冨3銆佸ご鍙戙�佽礉澹炽�佸崼鐢熷肪銆侀伩瀛曞銆佸彛棣欑硸銆佹墦鐏満銆佹ぐ瀛愬3銆佺尗鐮傘�侀潰鑶溿�侀宸剧焊銆佸ぇ楠ㄥご銆佸ザ鑼舵澂銆佺焊宸俱�佽洡铚婂3銆佺步瀛愬彾銆佺帀绫崇毊銆佸惛绠°�佽尪鍖呫�佺敇钄楃毊銆佸共鐕ュ墏銆佷竴娆℃�х瀛愩�佺帀绫冲3銆佺儫钂傘�佹箍绾稿肪銆佹Υ鑾插3銆佸崼鐢熺焊銆佸ぇ鏍告澹炽�佹寚鐢层�佸寘瑁呰銆佸彛绾€�佷竴娆℃�ф澂瀛愩�佽灪铔冲3銆佺墮鍒枫�佸鍗栭鐩掋�佹Υ鑾层�佸翱涓嶆箍銆佸瀮鍦捐銆佺墮鑶忕毊銆佸啺琚嬨�佽瀛愩�佺瑪銆佺焊灏胯¥銆佹Υ鑾叉牳銆佷竴娆℃�ч鐩掋�佽尪鍙跺寘銆佸彛缃┿�佸唴瑁ゃ�佹瘺宸俱�佸翱甯冦�侀櫠鐡风銆佺瑪鑺�佽偖鑴忓鏂欒銆佸洖褰㈤拡銆佺墮绛俱�侀鍝佸寘瑁呰銆佹按褰╃瑪銆佹绛�".split("銆�")
+
+# key_suffix -> (zh, en, ko, ja)
+TRANSLATIONS = {
+ "milkBox": ("鐗涘ザ鐩�", "Milk Carton", "鞖办湢韺�", "鐗涗钩銉戙儍銈�"),
+ "plastic": ("濉戞枡", "Plastic", "頂岆澕鞀ろ嫳", "銉椼儵銈广儊銉冦偗"),
+ "glassBottle": ("鐜荤拑鐡�", "Glass Bottle", "鞙犽Μ氤�", "銈儵銈圭摱"),
+ "glass": ("鐜荤拑", "Glass", "鞙犽Μ", "銈儵銈�"),
+ "paper": ("绾�", "Paper", "膦呾澊", "绱�"),
+ "clothes": ("琛f湇", "Clothes", "鞓�", "琛i"),
+ "brokenGlass": ("纰庣幓鐠�", "Broken Glass", "旯 鞙犽Μ", "鍓层倢銇熴偓銉┿偣"),
+ "can": ("鏄撴媺缃�", "Aluminum Can", "鞎岆(氙鸽妱 旌�", "銈€儷銉熺级"),
+ "plasticBox": ("濉戞枡鐩�", "Plastic Box", "頂岆澕鞀ろ嫳 靸侅瀽", "銉椼儵銈广儊銉冦偗绠�"),
+ "foamBoard": ("娉℃搏鏉�", "Foam Board", "鞀ろ嫲搿滍徏 韺�", "鐧烘场銉溿兗銉�"),
+ "powerBank": ("鍏呯數瀹�", "Power Bank", "氤挫“氚绊劙毽�", "銉€儛銈ゃ儷銉愩儍銉嗐儶銉�"),
+ "shoes": ("闉嬪瓙", "Shoes", "鞁犽皽", "闈�"),
+ "paperBox": ("绾哥洅", "Paper Box", "膦呾澊靸侅瀽", "绱欑"),
+ "foamBox": ("娉℃搏绠�", "Foam Box", "鞀ろ嫲搿滍徏 靸侅瀽", "鐧烘场銈广儊銉兗銉"),
+ "glassCup": ("鐜荤拑鏉�", "Glass Cup", "鞙犽Μ旎�", "銈儵銈广偝銉冦儣"),
+ "newspaper": ("鎶ョ焊", "Newspaper", "鞁犽", "鏂拌仦绱�"),
+ "plasticCup": ("濉戞枡鏉�", "Plastic Cup", "頂岆澕鞀ろ嫳 旎�", "銉椼儵銈广儊銉冦偗銈儍銉�"),
+ "wire": ("鐢电嚎", "Electric Wire", "鞝勳劆", "闆荤窔"),
+ "dataCable": ("鏁版嵁绾�", "Data Cable", "雿办澊韯� 旒�鞚措笖", "銉囥兗銈裤偙銉笺儢銉�"),
+ "waterBottle": ("鐭挎硥姘寸摱", "Water Bottle", "靸濎垬氤�", "銉熴儘銉┿儷銈︺偐銉笺偪銉笺儨銉堛儷"),
+ "pillow": ("鏋曞ご", "Pillow", "氩犼皽", "鏋�"),
+ "blade": ("鍒�鐗�", "Blade", "旃茧偁", "鍒冪墿"),
+ "screw": ("铻轰笣", "Screw", "雮橃偓", "銉嶃偢"),
+ "foamPlastic": ("娉℃搏濉戞枡", "Foam Plastic", "氚滍彫 頂岆澕鞀ろ嫳", "鐧烘场銉椼儵銈广儊銉冦偗"),
+ "yogurtTetraPak": ("閰稿ザ鍒╀箰鍖呰鐩�", "Yogurt Tetra Pak", "鞖旉惮毳错姼 韰岉姼霛柬尒", "銉ㄣ兗銈般儷銉堛儐銉堛儵銉戙儍銈�"),
+ "paperBag": ("绾歌", "Paper Bag", "膦呾澊氪夗埇", "绱欒"),
+ "cosmeticPlasticBottle": ("鍖栧鍝佸鏂欑┖鐡�", "Empty Cosmetic Plastic Bottle", "頇旍灔頀� 頂岆澕鞀ろ嫳 牍堧硲", "鍖栫钵鍝併儣銉┿偣銉併儍銈┖鐡�"),
+ "leatherShoes": ("鐨瀷", "Leather Shoes", "臧�欤届嫚", "闈╅澊"),
+ "cosmeticGlassBottle": ("鍖栧鍝佺幓鐠冪┖鐡�", "Empty Cosmetic Glass Bottle", "頇旍灔頀� 鞙犽Μ 牍堧硲", "鍖栫钵鍝併偓銉┿偣绌虹摱"),
+ "wineBottle": ("閰掔摱", "Wine Bottle", "靾犽硲", "閰掔摱"),
+ "chargingCable": ("鍏呯數绾�", "Charging Cable", "於╈爠 旒�鞚措笖", "鍏呴浕銈便兗銉栥儷"),
+ "flyer": ("骞垮憡鍗�", "Flyer", "甏戧碃 鞝勲嫧", "銉併儵銈�"),
+ "wastePlastic": ("搴熷鏂�", "Waste Plastic", "韽愴攲霛检姢韹�", "寤冦儣銉┿偣銉併儍銈�"),
+ "cigaretteBox": ("鐑熺洅", "Cigarette Box", "雼措鞍臧�", "銈裤儛銈炽伄绠�"),
+ "charger": ("鍏呯數鍣�", "Charger", "於╈爠旮�", "鍏呴浕鍣�"),
+ "book": ("涔︽湰", "Books", "毂�", "鏇哥睄"),
+ "beerBottle": ("鍟ら厭鐡�", "Beer Bottle", "毵レ<氤�", "銉撱兗銉摱"),
+ "cardboardBox": ("绾告澘绠�", "Cardboard Box", "瓿寪歆� 靸侅瀽", "娈点儨銉笺儷绠�"),
+ "woodChopsticks": ("鏈ㄧ瀛�", "Wooden Chopsticks", "雮橂 鞝撽皜霛�", "鏈ㄨ=绠�"),
+ "plushToy": ("姣涚粧鐜╁叿", "Plush Toy", "氪夓牅 鞚疙槙", "銇亜銇愩倠銇�"),
+ "bedSheet": ("琚崟", "Bed Sheet", "旃寑 鞁滍姼", "銈枫兗銉�"),
+ "scissors": ("鍓垁", "Scissors", "臧�鞙�", "銇仌銇�"),
+ "drinkPlasticBottle": ("楗枡濉戞枡鐡�", "Drink Plastic Bottle", "鞚岆 頂岆澕鞀ろ嫳氤�", "椋叉枡銉椼儵銈广儊銉冦偗銉溿儓銉�"),
+ "fabric": ("甯�", "Fabric", "觳�", "甯�"),
+ "dehumidifierBox": ("闄ゆ箍鐩�", "Dehumidifier Box", "鞝滌姷鞝� 靸侅瀽", "闄ゆ箍鍓ゃ儨銉冦偗銈�"),
+ "magnet": ("鍚搁搧鐭�", "Magnet", "鞛愳劃", "纾佺煶"),
+ "plasticWrap": ("濉戞枡鍖呰绾�", "Plastic Wrap", "頂岆澕鞀ろ嫳 韽灔歆�", "銉椼儵銈广儊銉冦偗鍖呰绱�"),
+ "quilt": ("琚瓙", "Quilt", "鞚措秷", "甯冨洠"),
+ "tetraPak": ("鍒╀箰鍖呰", "Tetra Pak", "韰岉姼霛柬尒", "銉嗐儓銉┿儜銉冦偗"),
+ "basketball": ("绡悆", "Basketball", "雴嶊惮瓿�", "銉愩偣銈便儍銉堛儨銉笺儷"),
+ "aluminumFoil": ("閾濈當", "Aluminum Foil", "鞎岆(氙鸽妱 順胳澕", "銈€儷銉熴儧銈ゃ儷"),
+ "socket": ("鎻掑骇", "Socket", "旖橃劶韸�", "銈炽兂銈汇兂銉�"),
+ "iron": ("閾�", "Iron", "觳�", "閴�"),
+ "key": ("閽ュ寵", "Key", "鞐挫嚑", "閸�"),
+ "printingPaper": ("鎵撳嵃绾�", "Printing Paper", "鞚胳噭鞖╈", "鍗板埛鐢ㄧ礄"),
+ "metal": ("閲戝睘", "Metal", "旮堨啀", "閲戝睘"),
+ "whitePaper": ("鐧界焊", "White Paper", "頋� 膦呾澊", "鐧界礄"),
+ "packagingBox": ("鍖呰绾哥洅", "Packaging Paper Box", "韽灔 膦呾澊靸侅瀽", "鍖呰绱欑"),
+ "plasticLid": ("濉戞枡鐩�", "Plastic Lid", "頂岆澕鞀ろ嫳 霘滉粦", "銉椼儵銈广儊銉冦偗钃�"),
+ "envelope": ("淇″皝", "Envelope", "氪夗埇", "灏佺瓛"),
+ "medicinePackaging": ("鑽搧鍖呰", "Medicine Packaging", "鞎� 韽灔", "钖伄鍖呰"),
+ "medicineBottle": ("鑽摱", "Medicine Bottle", "鞎诫硲", "钖摱"),
+ "lightBulb": ("鐏场", "Light Bulb", "鞝勱惮", "闆荤悆"),
+ "paintBucket": ("娌规紗妗�", "Paint Bucket", "韼橃澑韸� 韱�", "銉氥兂銈级"),
+ "medicine": ("鑽搧", "Medicine", "鞎巾拡", "钖搧"),
+ "expiredMedicine": ("杩囨湡鑽�", "Expired Medicine", "鞙犿喌旮绊暅 歆�雮� 鞎�", "鏈熼檺鍒囥倢銇柆"),
+ "rechargeableBattery": ("鍏呯數鐢垫睜", "Rechargeable Battery", "於╈爠 氚绊劙毽�", "鍏呴浕寮忛浕姹�"),
+ "nailPolish": ("鎸囩敳娌�", "Nail Polish", "毵る媹韥愳柎", "銉炪儖銈儱銈�"),
+ "storageBattery": ("钃勭數姹�", "Storage Battery", "於曥爠歆�", "钃勯浕姹�"),
+ "emptyMedicineBottle": ("绌鸿嵂鐡�", "Empty Medicine Bottle", "牍� 鞎诫硲", "绌恒伄钖摱"),
+ "hazardousWaste": ("鏈夊鍨冨溇", "Hazardous Waste", "鞙犿暣 鞊半爤旮�", "鏈夊銇斻伩"),
+ "expiredMedicine2": ("杩囨湡鑽搧", "Expired Medicine", "鞙犿喌旮绊暅 歆�雮� 鞚橃暯頀�", "鏈熼檺鍒囥倢鍖昏柆鍝�"),
+ "wasteMedicine": ("搴熻嵂鍝�", "Waste Medicine", "韽愳潣鞎巾拡", "寤冭柆鍝�"),
+ "lightTube": ("鐏", "Light Tube", "順曣磻霌�", "铔嶅厜鐏"),
+ "fluorescentTube": ("鑽у厜鐏", "Fluorescent Tube", "順曣磻霌标磤", "铔嶅厜绠�"),
+ "niCdBattery": ("闀嶉晧鐢垫睜", "Ni-Cd Battery", "雼堨紙旃措摐氘� 氚绊劙毽�", "銉嬨儍銈便儷銈儔銉熴偊銉犻浕姹�"),
+ "photo": ("鐓х墖", "Photo", "靷", "鍐欑湡"),
+ "fluorescentLamp": ("鑽у厜鐏�", "Fluorescent Lamp", "順曣磻霌�", "铔嶅厜鐏�"),
+ "hairDyeShell": ("鏌撳彂鍓傚3", "Hair Dye Shell", "鞐检儔鞝� 鞖╆赴", "銉樸偄銈儵銉煎鍣�"),
+ "eyeDrops": ("鐪艰嵂姘�", "Eye Drops", "鞎堨暯", "鐩柆"),
+ "energySavingLamp": ("鑺傝兘鐏�", "Energy-saving Lamp", "鞝堨爠霌�", "鐪併偍銉嶃儵銉炽儣"),
+ "insecticide": ("鏉�铏墏", "Insecticide", "靷挫订鞝�", "娈鸿櫕鍓�"),
+ "medicineTablet": ("鑽墖", "Medicine Tablet", "鞎届爼", "閷犲墹"),
+ "medicineTabletBox": ("鑽墖鐩�", "Medicine Tablet Box", "鞎届爼 靸侅瀽", "閷犲墹銇"),
+ "oralLiquidBottle": ("鍙f湇娑茶嵂鐡�", "Oral Liquid Medicine Bottle", "鞁滊熃 鞎诫硲", "鍐呮湇娑茶柆鐡�"),
+ "wasteMedicineBottle": ("搴熻嵂鐡�", "Waste Medicine Bottle", "韽愳暯氤�", "寤冭柆鐡�"),
+ "paint": ("娌规紗", "Paint", "韼橃澑韸�", "銉氥兂銈�"),
+ "buttonBattery": ("绾芥墸鐢垫睜", "Button Battery", "雼稊鞝勳", "銉溿偪銉抽浕姹�"),
+ "contraceptive": ("閬垮瓡鑽�", "Contraceptive", "頂检瀯鞎�", "閬垮钖�"),
+ "eyeDropsBottle": ("鐪艰嵂姘寸摱", "Eye Drops Bottle", "鞎堨暯氤�", "鐩柆鐡�"),
+ "film": ("鑳剁墖", "Film", "頃勲", "銉曘偅銉儬"),
+ "capsule": ("鑳跺泭", "Capsule", "旌§姁", "銈儣銈汇儷"),
+ "mercuryThermometer": ("姘撮摱娓╁害璁�", "Mercury Thermometer", "靾橃潃 鞓弰瓿�", "姘撮妧浣撴俯瑷�"),
+ "ratPoison": ("鑰侀紶鑽�", "Rat Poison", "欹愳暯", "銉嶃偤銉熻柆"),
+ "capsuleBlister": ("鑳跺泭鑽墖搴曟澘", "Capsule Blister Pack", "旌§姁 鞎岇暯 韺�", "銈儣銈汇儷銉婚尃鍓ゃ偡銉笺儓"),
+ "hairDyeCan": ("鏌撳彂鍓傜綈", "Hair Dye Can", "鞐检儔鞝� 旌�", "銉樸偄銈儵銉肩级"),
+ "energySavingBulb": ("鑺傝兘鐏场", "Energy-saving Bulb", "鞝堨爠 鞝勱惮", "鐪併偍銉嶉浕鐞�"),
+ "allExpiredMedicine": ("鍚勭被杩囨湡鑽搧", "All Types of Expired Medicine", "臧侅 鞙犿喌旮绊暅 歆�雮� 鞚橃暯頀�", "鍚勭ó鏈熼檺鍒囥倢鍖昏柆鍝�"),
+ "incandescentBulb": ("鐧界偨鐏场", "Incandescent Bulb", "氚膘棿鞝勱惮", "鐧界啽闆荤悆"),
+ "phoneBattery": ("鎵嬫満鐢垫睜", "Phone Battery", "頊措寑韽� 氚绊劙毽�", "鎼哄腐闆昏┍銉愩儍銉嗐儶銉�"),
+ "disinfectantBottle": ("娑堟瘨娑茬摱", "Disinfectant Bottle", "靻岆弲鞎‰硲", "娑堟瘨娑茬摱"),
+ "expiredTablets": ("杩囨湡鑽墖", "Expired Tablets", "鞙犿喌旮绊暅 歆�雮� 鞎届爼", "鏈熼檺鍒囥倢閷犲墹"),
+ "coldMedicine": ("鎰熷啋鑽�", "Cold Medicine", "臧愱赴鞎�", "棰ㄩ偑钖�"),
+ "disinfectant84Bottle": ("84娑堟瘨娑茬┖鐡�", "Empty 84 Disinfectant Bottle", "84 靻岆弲鞎� 牍堧硲", "84娑堟瘨娑茬┖鐡�"),
+ "nailPolishBottle": ("鎸囩敳娌圭摱", "Nail Polish Bottle", "毵る媹韥愳柎 氤�", "銉炪儖銈儱銈㈢摱"),
+ "sprayCan": ("鏉�姣掑柗闆剧綈", "Spray Can", "靷挫订 鞀ろ攧霠堨澊 旌�", "娈鸿櫕銈广儣銉兗缂�"),
+ "photoNegative": ("鐩哥墖搴曠墖", "Photo Negative", "靷 頃勲", "鍐欑湡銉曘偅銉儬"),
+ "chinesePatentMedicine": ("涓垚鑽�", "Chinese Patent Medicine", "欷戩劚 頃滌暯", "涓垚钖�"),
+ "filmRoll": ("鑳跺嵎", "Film Roll", "頃勲 搿�", "銉曘偅銉儬銉兗銉�"),
+ "medicineShell": ("鑽搧澹冲瓙", "Medicine Shell", "鞎� 韽灔 昊嶋嵃旮�", "钖伄鍖呰娈�"),
+ "mercury": ("姘撮摱", "Mercury", "靾橃潃", "姘撮妧"),
+ "photo2": ("鐩哥墖", "Photo", "靷", "鍐欑湡"),
+ "wastePaintBucket": ("搴熸补婕嗘《", "Waste Paint Bucket", "韽愴帢鞚疙姼 韱�", "寤冦儦銉炽偔缂�"),
+ "expiredDrug": ("杩囨湡鑽墿", "Expired Drug", "鞙犿喌旮绊暅 歆�雮� 鞎诫", "鏈熼檺鍒囥倢钖墿"),
+ "medicineBlister": ("鑽搧閾濆鏉�", "Medicine Blister Pack", "鞎� 鞎岆(氙鸽妱 韺�", "钖伄銈€儷銉熴儣銉┿偣銉併儍銈澘"),
+ "cockroachMedicine": ("锜戣瀭鑽�", "Cockroach Medicine", "氚旐�措矊霠� 鞎�", "銈淬偔銉栥儶钖�"),
+ "cockroachBall": ("锜戣瀭涓�", "Cockroach Ball", "氚旐�措矊霠� 鞎岇暯", "銈淬偔銉栥儶涓�"),
+ "capsuleTablet": ("鑳跺泭鑽墖", "Capsule and Tablet", "旌§姁 鞎岇暯", "銈儣銈汇儷銉婚尃鍓�"),
+ "disinfectantTablet": ("娑堟瘨鑽墖", "Disinfectant Tablet", "靻岆弲 鞝曥牅", "娑堟瘨閷�"),
+ "energySavingTube": ("鑺傝兘鐏", "Energy-saving Tube", "鞝堨爠 順曣磻霌标磤", "鐪併偍銉嶈泹鍏夌"),
+ "melonSeedShell": ("鐡滃瓙澹�", "Melon Seed Shell", "頃措皵霛缄赴鞌� 昊嶌", "鐡滃瓙銇"),
+ "eggShell": ("楦¤泲澹�", "Egg Shell", "雼眬昊嶌", "鍗点伄娈�"),
+ "cornCob": ("鐜夌背妫�", "Corn Cob", "鞓レ垬靾橂寑", "銇ㄣ亞銈傘倣銇撱仐銇姱"),
+ "eggshell": ("铔嬪3", "Eggshell", "瓿勲瀫 昊嶌", "鍗垫"),
+ "corn": ("鐜夌背", "Corn", "鞓レ垬靾�", "銇ㄣ亞銈傘倣銇撱仐"),
+ "walnut": ("鏍告", "Walnut", "順鸽憪", "銈儷銉�"),
+ "peanutShell": ("鑺辩敓澹�", "Peanut Shell", "霑呾僵 昊嶌", "銉斻兗銉娿儍銉勩伄娈�"),
+ "tea": ("鑼跺彾", "Tea Leaves", "彀混瀻", "鑼惰憠"),
+ "lobsterShell": ("榫欒櫨澹�", "Lobster Shell", "霝嶌姢韯� 昊嶌", "銉儢銈广偪銉笺伄娈�"),
+ "crayfish": ("灏忛緳铏�", "Crayfish", "臧�鞛�", "銈躲儶銈儖"),
+ "crabShell": ("锜瑰3", "Crab Shell", "瓴� 昊嶌", "銈儖銇"),
+ "chickenBone": ("楦¢澶�", "Chicken Bone", "雼紙", "槎忋伄楠�"),
+ "melonSeed": ("鐡滃瓙", "Melon Seed", "頃措皵霛缄赴鞌�", "鐡滃瓙"),
+ "crabShell2": ("铻冭煿澹�", "Crab Shell", "瓴� 昊嶋嵃旮�", "銈儖銇"),
+ "cookedCornCob": ("鐔熺帀绫虫", "Cooked Corn Cob", "鞚淀瀸 鞓レ垬靾橂寑", "鑼广仹銇熴仺銇嗐倐銈嶃亾銇椼伄鑺�"),
+ "pistachioShell": ("寮�蹇冩灉澹�", "Pistachio Shell", "頂检姢韮�旃橃槫 昊嶌", "銉斻偣銈裤儊銈伄娈�"),
+ "crayfishShell": ("灏忛緳铏惧3", "Crayfish Shell", "臧�鞛� 昊嶌", "銈躲儶銈儖銇"),
+ "edamameShell": ("姣涜眴澹�", "Edamame Shell", "鞕勲憪旖� 昊嶌", "鏋濊眴銇"),
+ "shrimpShell": ("闇炲3", "Shrimp Shell", "靸堨毎 昊嶌", "銈ㄣ儞銇"),
+ "bananaPeel": ("棣欒晧鐨�", "Banana Peel", "氚旊倶雮� 昊嶌", "銉愩儕銉娿伄鐨�"),
+ "watermelonRind": ("瑗跨摐鐨�", "Watermelon Rind", "靾橂皶 昊嶌", "銈广偆銈伄鐨�"),
+ "chestnutShell": ("鏍楀瓙澹�", "Chestnut Shell", "氚� 昊嶌", "鏍椼伄娈�"),
+ "fishBone": ("楸奸澶�", "Fish Bone", "靸濎劆 爰�", "榄氥伄楠�"),
+ "lobster": ("榫欒櫨", "Lobster", "霝嶌姢韯�", "銉儢銈广偪銉�"),
+ "cornCore": ("鐜夌背鑺�", "Corn Core", "鞓レ垬靾� 鞁�", "銇ㄣ亞銈傘倣銇撱仐鑺�"),
+ "melonSeedPiece": ("鐡滃瓙鐗�", "Melon Seed Piece", "頃措皵霛缄赴鞌� 臁瓣皝", "鐡滃瓙銇牬鐗�"),
+ "flower": ("鑺�", "Flower", "杲�", "鑺�"),
+ "coffeeGrounds": ("鍜栧暋娓�", "Coffee Grounds", "旎ろ敿 彀岅杭旮�", "銈炽兗銉掋兗銇嬨仚"),
+ "porkRibs": ("鎺掗", "Pork Ribs", "臧堧箘", "銈广儦銈€儶銉�"),
+ "zongzi": ("绮藉瓙", "Zongzi", "膦呾瀽", "銇°伨銇�"),
+ "herbalDregs": ("涓嵂娓�", "Herbal Medicine Dregs", "頃滌暯 彀岅杭旮�", "婕㈡柟钖伄銇嬨仚"),
+ "egg": ("楦¤泲", "Egg", "雼眬", "鍗�"),
+ "crab": ("铻冭煿", "Crab", "瓴�", "銈儖"),
+ "lycheeShell": ("鑽旀灊澹�", "Lychee Shell", "毽箻 昊嶌", "銉┿偆銉併伄娈�"),
+ "peach": ("妗冨瓙", "Peach", "氤奠埈鞎�", "妗�"),
+ "plumPit": ("璇濇鏍�", "Preserved Plum Pit", "頇旊Г 鞌�", "姊呭共銇椼伄鏍�"),
+ "jujubePit": ("鏋f牳", "Jujube Pit", "雽�於� 鞌�", "銉娿儎銉°伄鏍�"),
+ "chickenBone2": ("楦¢", "Chicken Bone", "雼紙", "槎忛"),
+ "expiredFood": ("杩囨湡椋熷搧", "Expired Food", "鞙犿喌旮绊暅 歆�雮� 鞁濏拡", "鏈熼檺鍒囥倢椋熷搧"),
+ "fishBone2": ("楸奸", "Fish Bone", "靸濎劆 臧�鞁�", "榄氶"),
+ "apple": ("鑻规灉", "Apple", "靷臣", "銈娿倱銇�"),
+ "lycheePit": ("鑽旀灊鏍�", "Lychee Pit", "毽箻 鞌�", "銉┿偆銉併伄鏍�"),
+ "bayberry": ("鏉ㄦ", "Bayberry", "鞏戨Г", "銉ゃ優銉€儮"),
+ "watermelonSeed": ("瑗跨摐绫�", "Watermelon Seed", "靾橂皶鞌�", "銈广偆銈伄绋�"),
+ "chestnutShell2": ("鏉挎牀澹�", "Chestnut Shell", "氚� 昊嶌", "鏍椼伄娈�"),
+ "cockroach2": ("锜戣瀭", "Cockroach", "氚旐�措矊霠�", "銈淬偔銉栥儶"),
+ "fruitPeel": ("鏋滅毊", "Fruit Peel", "瓿检澕 昊嶌", "鏋滅墿銇毊"),
+ "mangoPit": ("鑺掓灉鏍�", "Mango Pit", "毵濌碃 鞌�", "銉炪兂銈淬兗銇牳"),
+ "peanut": ("鑺辩敓", "Peanut", "霑呾僵", "銉斻兗銉娿儍銉�"),
+ "driedPeanutShell": ("骞茶姳鐢熷3", "Dried Peanut Shell", "毵愲Π 霑呾僵 昊嶌", "骞层仐銇熴償銉笺儕銉冦儎銇"),
+ "biscuit": ("楗煎共", "Biscuit", "牍勳姢韨�", "銉撱偣銈便儍銉�"),
+ "watermelon": ("瑗跨摐", "Watermelon", "靾橂皶", "銈广偆銈�"),
+ "freshFlower": ("椴滆姳", "Fresh Flower", "靸濏檾", "鐢熻姳"),
+ "redJujubePit": ("绾㈡灒鏍�", "Red Jujube Pit", "雽�於� 鞌�", "璧ゃ儕銉勩儭銇牳"),
+ "lusuji": ("鑺︾ǚ", "Sorghum", "靾橃垬", "鑺︾ǚ"),
+ "appleCore": ("鑻规灉鏍�", "Apple Core", "靷臣 鞌�", "銈娿倱銇斻伄鑺�"),
+ "waterBambooPeel": ("鑼櫧鐨�", "Water Bamboo Peel", "甑愲氨頂�", "銈躲兗銈点偆銇毊"),
+ "bread": ("闈㈠寘", "Bread", "牍�", "銉戙兂"),
+ "banana": ("棣欒晧", "Banana", "氚旊倶雮�", "銉愩儕銉�"),
+ "teaResidue": ("鑼跺彾娓�", "Tea Residue", "彀混瀻 彀岅杭旮�", "鑼惰憠銇嬨仚"),
+ "plasticBag": ("濉戞枡琚�", "Plastic Bag", "牍勲嫄氪夓", "銉撱儖銉笺儷琚�"),
+ "zongziLeaf": ("绮藉彾", "Zongzi Leaf", "膦呾瀽 鞛�", "銇°伨銇嶃伄钁�"),
+ "walnutShell": ("鏍告澹�", "Walnut Shell", "順鸽憪 昊嶌", "銈儷銉熴伄娈�"),
+ "hair": ("澶村彂", "Hair", "毹鸽Μ旃措澖", "楂伄姣�"),
+ "shell": ("璐濆3", "Shell", "臁瓣皽昊嶌", "璨濇"),
+ "sanitaryPad": ("鍗敓宸�", "Sanitary Pad", "靸濍Μ雽�", "鐢熺悊鐢ㄣ儕銉椼偔銉�"),
+ "condom": ("閬垮瓡濂�", "Condom", "旖橂彅", "銈炽兂銉夈兗銉�"),
+ "chewingGum": ("鍙i绯�", "Chewing Gum", "昊�", "銈儬"),
+ "lighter": ("鎵撶伀鏈�", "Lighter", "霛检澊韯�", "銉┿偆銈裤兗"),
+ "coconutShell": ("妞板瓙澹�", "Coconut Shell", "旖旍綌雱� 昊嶌", "銈炽偝銉娿儍銉勩伄娈�"),
+ "catLitter": ("鐚爞", "Cat Litter", "瓿犾枒鞚� 氇灅", "鐚爞"),
+ "faceMask": ("闈㈣啘", "Face Mask", "毵堨姢韥尒", "銉曘偋銈ゃ偣銉炪偣銈�"),
+ "tissue": ("椁愬肪绾�", "Tissue Paper", "雰呿偍", "銉娿儣銈兂"),
+ "bigBone": ("澶ч澶�", "Big Bone", "韥� 爰�", "澶с亶銇"),
+ "milkTeaCup": ("濂惰尪鏉�", "Milk Tea Cup", "氚�韥嫲 旎�", "銈裤償銈偒銉嗐偅銉笺偒銉冦儣"),
+ "paperTowel": ("绾稿肪", "Paper Towel", "頊挫", "銉嗐偅銉冦偡銉�"),
+ "clamShell": ("铔よ湂澹�", "Clam Shell", "臁瓣皽 昊嶌", "銈€偟銉伄娈�"),
+ "zongziLeaf2": ("绮藉瓙鍙�", "Zongzi Leaf", "膦呾瀽 鞛�", "銇°伨銇嶃伄钁�"),
+ "cornHusk": ("鐜夌背鐨�", "Corn Husk", "鞓レ垬靾� 昊嶌", "銇ㄣ亞銈傘倣銇撱仐銇毊"),
+ "straw": ("鍚哥", "Straw", "牍寑", "銈广儓銉兗"),
+ "teaBag": ("鑼跺寘", "Tea Bag", "韹半氨", "銉嗐偅銉笺儛銉冦偘"),
+ "sugarcanePeel": ("鐢樿敆鐨�", "Sugarcane Peel", "靷儠靾橃垬 昊嶌", "銈点儓銈︺偔銉撱伄鐨�"),
+ "desiccant": ("骞茬嚗鍓�", "Desiccant", "瓯挫“鞝�", "涔剧嚗鍓�"),
+ "disposableChopsticks": ("涓�娆℃�х瀛�", "Disposable Chopsticks", "鞚柬殞鞖� 鞝撽皜霛�", "浣裤亜鎹ㄣ仸绠�"),
+ "cornShell": ("鐜夌背澹�", "Corn Shell", "鞓レ垬靾� 昊嶋嵃旮�", "銇ㄣ亞銈傘倣銇撱仐銇"),
+ "cigarette": ("鐑熻拏", "Cigarette Butt", "雼措鞍杲侅磮", "鍚搞亜娈�"),
+ "wetWipe": ("婀跨焊宸�", "Wet Wipe", "氍柬嫲鞀�", "銈︺偋銉冦儓銉嗐偅銉冦偡銉�"),
+ "durianShell": ("姒磋幉澹�", "Durian Shell", "霊愲Μ鞎� 昊嶌", "銉夈儶銈€兂銇"),
+ "toiletPaper": ("鍗敓绾�", "Toilet Paper", "頇旍灔歆�", "銉堛偆銉儍銉堛儦銉笺儜銉�"),
+ "bigWalnutShell": ("澶ф牳妗冨3", "Big Walnut Shell", "韥� 順鸽憪 昊嶌", "澶с亶銇偗銉儫銇"),
+ "nail": ("鎸囩敳", "Nail", "靻愴啽", "鐖�"),
+ "packagingBag": ("鍖呰琚�", "Packaging Bag", "韽灔氪夓", "鍖呰琚�"),
+ "lipstick": ("鍙g孩", "Lipstick", "毽届姢韹�", "鍙g磪"),
+ "disposableCup": ("涓�娆℃�ф澂瀛�", "Disposable Cup", "鞚柬殞鞖� 旎�", "浣裤亜鎹ㄣ仸銈儍銉�"),
+ "snailShell": ("铻鸿洺澹�", "Snail Shell", "瓿眳鞚� 昊嶌", "宸汇亶璨濄伄娈�"),
+ "toothbrush": ("鐗欏埛", "Toothbrush", "旃啍", "姝儢銉┿偡"),
+ "takeoutBox": ("澶栧崠椁愮洅", "Takeout Box", "氚半嫭 鞖╆赴", "銉嗐偆銈偄銈︺儓瀹瑰櫒"),
+ "durian": ("姒磋幉", "Durian", "霊愲Μ鞎�", "銉夈儶銈€兂"),
+ "diaper": ("灏夸笉婀�", "Diaper", "旮办爛攴�", "銇娿個銇�"),
+ "trashBag": ("鍨冨溇琚�", "Trash Bag", "鞊半爤旮半磯歆�", "銈淬儫琚�"),
+ "toothpasteTube": ("鐗欒啅鐨�", "Toothpaste Tube", "旃橃暯 韸滊笇", "姝(銇嶃儊銉ャ兗銉�"),
+ "icePack": ("鍐拌", "Ice Pack", "鞎勳澊鞀ろ尒", "淇濆喎鍓�"),
+ "sock": ("琚滃瓙", "Sock", "鞏戨", "闈翠笅"),
+ "pen": ("绗�", "Pen", "韼�", "銉氥兂"),
+ "diaper2": ("绾稿翱瑁�", "Diaper", "旮办爛攴�", "绱欍亰銈�銇�"),
+ "durianPit": ("姒磋幉鏍�", "Durian Pit", "霊愲Μ鞎� 鞌�", "銉夈儶銈€兂銇ó"),
+ "disposableLunchBox": ("涓�娆℃�ч鐩�", "Disposable Lunch Box", "鞚柬殞鞖� 霃勳嫓霛巾喌", "浣裤亜鎹ㄣ仸寮佸綋绠�"),
+ "teaBag2": ("鑼跺彾鍖�", "Tea Bag", "彀混瀻 韹半氨", "鑼惰憠銉戙儍銈�"),
+ "mask": ("鍙g僵", "Mask", "毵堨姢韥�", "銉炪偣銈�"),
+ "underwear": ("鍐呰¥", "Underwear", "靻嶌樂", "涓嬬潃"),
+ "towel": ("姣涘肪", "Towel", "靾橁贝", "銈裤偑銉�"),
+ "diaper3": ("灏垮竷", "Diaper", "旮办爛攴�", "銇娿個銇�"),
+ "ceramicBowl": ("闄剁摲纰�", "Ceramic Bowl", "霃勳瀽旮� 攴鸽", "闄跺櫒銇"),
+ "penRefill": ("绗旇姱", "Pen Refill", "韼滌嫭", "銉氥兂鑺�"),
+ "dirtyPlasticBag": ("鑲剰濉戞枡琚�", "Dirty Plastic Bag", "雿旊煬鞖� 牍勲嫄氪夓", "姹氥倢銇熴儞銉嬨兗銉"),
+ "paperClip": ("鍥炲舰閽�", "Paper Clip", "韥措", "銈儶銉冦儣"),
+ "toothpick": ("鐗欑", "Toothpick", "鞚挫懁鞁滉皽", "鐖鏋�"),
+ "foodPackagingBag": ("椋熷搧鍖呰琚�", "Food Packaging Bag", "鞁濏拡 韽灔氪夓", "椋熷搧鍖呰琚�"),
+ "watercolorPen": ("姘村僵绗�", "Watercolor Pen", "氍缄皭韼�", "姘村僵銉氥兂"),
+ "cottonSwab": ("妫夌", "Cotton Swab", "氅措磯", "缍挎"),
+}
+
+# Map Chinese name -> key_suffix
+ZH_TO_KEY = {v[0]: k for k, v in TRANSLATIONS.items()}
+
+def slug_from_zh(zh, category, index):
+ if zh in ZH_TO_KEY:
+ return ZH_TO_KEY[zh]
+ # fallback: category prefix + index
+ return f"{category}{index:03d}"
+
+def build_items():
+ items = []
+ for category_id, names in [
+ ("recyclable", RECYCLABLE),
+ ("hazardous", HAZARDOUS),
+ ("wet", WET),
+ ("dry", DRY),
+ ]:
+ for i, zh in enumerate(names):
+ key_suffix = slug_from_zh(zh, category_id, i)
+ if key_suffix not in TRANSLATIONS:
+ TRANSLATIONS[key_suffix] = (zh, zh, zh, zh) # placeholder
+ key = f"item.{key_suffix}"
+ item_id = re.sub(r'(?<!^)(?=[A-Z])', '-', key_suffix).lower()
+ items.append({
+ "id": item_id,
+ "nameKey": key,
+ "categoryId": category_id
+ })
+ return items
+
+def load_zh_base():
+ with open(os.path.join(BASE, "config", "i18n", "zh.json"), encoding="utf-8") as f:
+ return json.load(f)
+
+def build_lang_file(base_zh, lang_index):
+ result = {}
+ for k, v in base_zh.items():
+ if k.startswith("item."):
+ suffix = k[5:] # strip "item."
+ if suffix in TRANSLATIONS:
+ result[k] = TRANSLATIONS[suffix][lang_index]
+ else:
+ result[k] = v
+ elif k == "lang.ja":
+ result[k] = ["", "鏃ユ湰瑾�", "鏃ユ湰瑾�", "鏃ユ湰瑾�"][lang_index]
+ elif k == "lang.zh":
+ result[k] = ["涓枃", "Chinese", "欷戧淡鞏�", "涓浗瑾�"][lang_index]
+ elif k == "lang.en":
+ result[k] = ["English", "English", "鞓侅柎", "鑻辫獮"][lang_index]
+ elif k == "lang.ko":
+ result[k] = ["頃滉淡鞏�", "Korean", "頃滉淡鞏�", "闊撳浗瑾�"][lang_index]
+ else:
+ # UI strings - translate from updated zh.json
+ result[k] = translate_ui(k, v, lang_index)
+ return result
+
+def translate_ui(key, zh_val, lang_index):
+ UI = {
+ "page.title": ("涓婃捣甯傚瀮鍦惧垎绫绘煡璇�", "Shanghai Waste Sorting Guide", "靸來晿鞚� 鞊半爤旮� 攵勲 臁绊殞", "涓婃捣甯傘偞銉熷垎鍒ャ偓銈ゃ儔"),
+ "header.title": ("涓婃捣甯傛棩甯哥敓娲诲瀮鍦炬�庝箞鍒嗭紵", "How to Sort Daily Waste in Shanghai?", "靸來晿鞚� 靸濏櫆 鞊半爤旮�, 鞏措柣瓴� 攵勲頃犼箤鞖�?", "涓婃捣甯傘伄鐢熸椿銈淬儫銇仼銇嗗垎鍒ャ仚銈嬶紵"),
+ "btn.home": ("棣栭〉", "Home", "頇�", "銉涖兗銉�"),
+ "btn.query": ("鏌ヨ", "Search", "臁绊殞", "妞滅储"),
+ "btn.voice": ("闀挎寜璇煶", "Hold to Speak", "旮戈矊 雸岆煬 鞚岇劚", "闀锋娂銇楅煶澹�"),
+ "btn.standard": ("鎶曟斁鏍囧噯", "Disposal Rules", "氚办稖 旮办", "鎺掑嚭鍩烘簴"),
+ "btn.home.short": ("棣栭〉", "Home", "頇�", "銉涖兗銉�"),
+ "search.placeholder": ("杈撳叆鍨冨溇鍚嶇О", "Enter waste name", "鞊半爤旮� 鞚措 鞛呺牓", "銈淬儫銇悕鍓嶃倰鍏ュ姏"),
+ "search.notFoundHint": ("鎴戞壘涓嶅埌浣犳兂瑕佺殑锛岀湅鐪嬩笅闈㈣繖浜涘彲浠ュ悧锛�", "I couldn't find an exact match. How about these?", "鞗愴晿鞁滊姅 頃鞚� 彀眷 氇豁枅鞀惦媹雼�. 鞎勲灅 頃鞚� 鞏措枲靹胳殧?", "銇婃帰銇椼伄闋呯洰銇岃銇ゃ亱銈娿伨銇涖倱銇с仐銇熴�備互涓嬨伅銇勩亱銇屻仹銇欍亱锛�"),
+ "search.referenceHint": ("璇峰弬鑰冧互涓嬪垎绫讳俊鎭��", "Please refer to the following categories.", "鞎勲灅 攵勲 鞝曤炒毳� 彀戈碃頃� 欤检劯鞖�.", "浠ヤ笅銇垎椤炴儏鍫便倰銇斿弬鐓с亸銇犮仌銇勩��"),
+ "search.noResults": ("鏈壘鍒扮浉鍏冲瀮鍦撅紝璇峰皾璇曞叾浠栧叧閿瘝銆�", "No results found. Please try another keyword.", "甏�霠� 頃鞚� 彀眷潉 靾� 鞐嗢姷雼堧嫟. 雼るジ 韨れ泴霌滊ゼ 鞁滊弰頃� 氤挫劯鞖�.", "闁㈤�c仚銈嬮爡鐩亴瑕嬨仱銇嬨倞銇俱仜銈撱�傚垾銇偔銉笺儻銉笺儔銈掋亰瑭︺仐銇忋仩銇曘亜銆�"),
+ "footer.copyright": ("涓婃捣浜敵 Copyright 漏 2026", "Shanghai Jingshen Copyright 漏 2026", "靸來晿鞚� 歆曥厴 Copyright 漏 2026", "涓婃捣浜敵 Copyright 漏 2026"),
+ "welcome.title": ("娓╅Θ鎻愮ず", "Friendly Reminder", "鞎堧偞 毵愳攢", "銇旀鍐�"),
+ "welcome.p1": ("1銆佽杈撳叆鍨冨溇姝e父鐨勪腑鏂囧悕绉帮紙鍖呭惈鏉愯川锛夛紝濡傜幓鐠冪摱锛屼竴娆℃�у鏂欐澂銆侀櫠鐡风绛夈��", "1. Please enter the standard Chinese name of the waste (including material), such as glass bottle, disposable plastic cup, ceramic bowl, etc.", "1. 鞊半爤旮办潣 鞝曥儊鞝侅澑 欷戧淡鞏� 鞚措(鞛 韽暔)鞚� 鞛呺牓頃橃劯鞖�. 鞓�: 鞙犽Μ氤�, 鞚柬殞鞖� 頂岆澕鞀ろ嫳 旎�, 霃勳瀽旮� 攴鸽 霌�.", "1. 銈淬儫銇寮忋仾涓浗瑾炲悕绉帮紙鏉愯唱銈掑惈銈�锛夈倰鍏ュ姏銇椼仸銇忋仩銇曘亜銆備緥锛氥偓銉┿偣鐡躲�佷娇銇勬崹銇︺儣銉┿偣銉併儍銈偒銉冦儣銆侀櫠鍣ㄣ伄纰椼仾銇┿��"),
+ "welcome.p2": ("2銆佺敓娲诲瀮鍦惧垎绫荤殑鍏蜂綋鍒嗙被鏍囧噯锛氭槸鏍规嵁缁忔祹绀句細鍙戝睍姘村钩銆佺敓娲诲瀮鍦剧壒鎬у拰澶勭悊鍒╃敤鏂规硶浜堜互缁嗗寲璋冩暣鐨勩��", "2. The specific classification standards for household waste sorting are refined and adjusted based on economic and social development, waste characteristics, and treatment methods.", "2. 靸濏櫆 鞊半爤旮� 攵勲鞚� 甑泊鞝侅澑 旮办鞚� 瓴届牅路靷殞 氚滌爠 靾橃, 靸濏櫆 鞊半爤旮� 韸轨劚 氚� 觳橂Μ路鞚挫毄 氚╇矔鞐� 霐半澕 靹鸽秳頇斅缝“鞝曤惄雼堧嫟.", "2. 鐢熸椿銈淬儫鍒嗛銇叿浣撶殑鍩烘簴銇�佺祵娓堢ぞ浼氱櫤灞曟按婧栥�佺敓娲汇偞銉熴伄鐗规�с�佸嚘鐞嗐兓鍒╃敤鏂规硶銇熀銇ャ亜銇︾窗鍒嗗寲銉昏鏁淬仌銈屻伨銇欍��"),
+ "welcome.p3": ("3銆佹湰鏌ヨ绯荤粺浠呬緵鍙傝�冿紝鍏蜂綋鍒嗙被瑕佹眰浠ュ睘鍦颁笓涓氱鐞嗛儴闂ㄤ负鍑嗐��", "3. This query system is for reference only. Please follow the requirements of local professional management authorities.", "3. 氤� 臁绊殞 鞁滌姢韰滌潃 彀戈碃鞖╈澊氅�, 甑泊鞝侅澑 攵勲 鞖旉贝鞚� 甏�頃� 鞝勲 甏�毽� 攵�靹� 旮办鞚� 霐半雼堧嫟.", "3. 鏈绱€偡銈广儐銉犮伅鍙傝�冪敤銇с仚銆傚叿浣撶殑銇垎椤炶浠躲伅绠¤絼銇皞闁�绠$悊閮ㄩ杸銇熀婧栥伀寰撱仯銇︺亸銇犮仌銇勩��"),
+ "welcome.confirm": ("鐭ラ亾浜�", "Got it", "鞎岅矤鞀惦媹雼�", "浜嗚В"),
+ "disposal.suggestLabel": ("寤鸿鎶曟斁鑷筹細", "Suggested disposal to:", "氚办稖 甓岇灔:", "鎺掑嚭鍏堬細"),
+ "disposal.tipsTitle": ("灏忕鏅�", "Did You Know?", "鞎岇晞霊愳劯鞖�", "璞嗙煡璀�"),
+ "cat.recyclable": ("鍙洖鏀剁墿", "Recyclables", "鞛櫆鞖╉拡", "璩囨簮銇斻伩"),
+ "cat.recyclable.desc": ("鏄寚搴熺焊寮犮�佸簾濉戞枡銆佸簾鐜荤拑鍒跺搧銆佸簾閲戝睘銆佸簾缁囩墿绛夐�傚疁鍥炴敹銆佸彲寰幆鍒╃敤鐨勭敓娲诲簾寮冪墿銆�", "Waste paper, waste plastic, waste glass products, waste metal, waste textiles and other household waste suitable for recycling and reuse.", "韽愳, 韽愴攲霛检姢韹�, 韽愳湢毽� 鞝滍拡, 韽愱笀靻�, 韽愳氍� 霌� 鞛櫆鞖� 氚� 靾滍櫂 鞚挫毄鞚� 臧�電ロ暅 靸濏櫆 韽愱赴氍检潉 毵愴暕雼堧嫟.", "寤冪礄銆佸粌銉椼儵銈广儊銉冦偗銆佸粌銈儵銈硅=鍝併�佸粌閲戝睘銆佸粌绻婄董銇仼銆併儶銈点偆銈儷銉诲啀鍒╃敤銇仼銇椼仧鐢熸椿寤冩鐗┿倰鎸囥仐銇俱仚銆�"),
+ "cat.recyclable.standard": ("1. 杞绘姇杞绘斁\n2. 娓呮磥骞茬嚗锛岄伩鍏嶆薄鏌撱�俓n3. 搴熺焊绫诲敖閲忓钩鏁达紝淇濇寔骞茬嚗銆俓n4. 濉戞枡绫诲簲鍘婚櫎娈嬬暀鐗╋紝娲楀噣鏅惧共銆俓n5. 绔嬩綋鍖呰鐗╄娓呯┖鍐呭鐗╋紝娓呮磥鍚庡帇鎵佹姇鏀� \n6. 鏈夊皷閿愯竟瑙掔殑,搴斿寘瑁瑰悗鎶曟斁銆俓n7. 閲戝睘绫诲簲鍘婚櫎娈嬬暀鐗╋紝鍘嬫墎鍚庢姇鏀俱�俓n8. 缁囩墿绫诲簲娲楀噣鏅惧共锛屾姌鍙犳暣榻愩��", "1. Handle gently.\n2. Keep clean and dry to avoid contamination.\n3. Paper should be flat and dry.\n4. Plastic should be rinsed and dried.\n5. Empty and clean 3D packaging, then flatten.\n6. Wrap items with sharp edges.\n7. Metal should be rinsed and flattened.\n8. Textiles should be washed, dried, and folded.", "1. 臧�氤嶊矊 雱l溂靹胳殧.\n2. 旯仐頃橁碃 瓯挫“頃橁矊, 鞓れ椉鞚� 頂柬晿靹胳殧.\n3. 膦呾澊電� 韽夗弶頃橁矊, 瓯挫“頃橁矊 鞙犾頃橃劯鞖�.\n4. 頂岆澕鞀ろ嫳鞚� 鞛旍棳氍检潉 鞝滉卑頃橁碃 項龟惮鞏� 毵愲Μ靹胳殧.\n5. 鞛呾泊 韽灔鞚� 雮挫毄氍检潉 牍勳毎瓿� 觳唽 頉� 雸岆煬靹� 氚办稖頃橃劯鞖�.\n6. 雮犾勾搿滌毚 氇劀毽姅 臧愳嫺靹� 氚办稖頃橃劯鞖�.\n7. 旮堨啀鞚� 鞛旍棳氍检潉 鞝滉卑頃橁碃 雸岆煬靹� 氚办稖頃橃劯鞖�.\n8. 歆侂鞚� 靹疙儊 頉� 毵愲Μ瓿� 鞝戩柎靹� 氚办稖頃橃劯鞖�.", "1. 杌姐亸鍏ャ倢銇︺亸銇犮仌銇勩�俓n2. 娓呮綌銇т咕鐕ャ仐銇熺姸鎱嬨倰淇濄仭銆佹睔鏌撱倰閬裤亼銇︺亸銇犮仌銇勩�俓n3. 绱欓銇仹銇嶃倠銇犮亼骞炽倝銇�佷咕鐕ャ仌銇涖仸銇忋仩銇曘亜銆俓n4. 銉椼儵銈广儊銉冦偗椤炪伅娈嬬疆鐗┿倰鍙栥倞闄ゃ亶銆佹礂銇c仸涔俱亱銇椼仸銇忋仩銇曘亜銆俓n5. 绔嬩綋鍖呰銇腑韬倰绌恒伀銇椼�佹竻鎺冨緦銇桨銇椼仸鎺掑嚭銇椼仸銇忋仩銇曘亜銆俓n6. 閶亜瑙掋亴銇傘倠銈傘伄銇寘銈撱仹鎺掑嚭銇椼仸銇忋仩銇曘亜銆俓n7. 閲戝睘椤炪伅娈嬬疆鐗┿倰鍙栥倞闄ゃ亶銆佹桨銇椼仸鎺掑嚭銇椼仸銇忋仩銇曘亜銆俓n8. 绻婄董椤炪伅娲椼仯銇︿咕銇嬨仐銆併仧銇熴倱銇ф帓鍑恒仐銇︺亸銇犮仌銇勩��"),
+ "cat.hazardous": ("鏈夊鍨冨溇", "Hazardous Waste", "鞙犿暣 鞊半爤旮�", "鏈夊銇斻伩"),
+ "cat.hazardous.desc": ("瀵逛汉浣撳仴搴锋垨鑷劧鐜閫犳垚鐩存帴鎴栨綔鍦ㄥ嵄瀹崇殑鐢熸椿搴熷純鐗┿�備富瑕佸寘鎷細搴熺數姹犮�佸簾鐏銆佸簾鑽搧銆佸簾娌规紗鍙婂叾瀹瑰櫒绛夈��", "Household waste that poses direct or potential harm to human health or the natural environment, including waste batteries, light tubes, medicine, paint and containers.", "鞚胳泊 瓯搓皶鞚措倶 鞛愳棸 頇橁步鞐� 歆侅爲 霕愲姅 鞛犾灛鞝� 鞙勴暣毳� 欷� 靾� 鞛堧姅 靸濏櫆 韽愱赴氍�. 韽愲鞍韯半Μ, 韽愲摫甏�, 韽愳潣鞎巾拡, 韽愴帢鞚疙姼 氚� 鞖╆赴 霌膘澊 韽暔霅╇媹雼�.", "浜轰綋銇仴搴枫倓鑷劧鐠板銇洿鎺ョ殑銇俱仧銇綔鍦ㄧ殑銇嵄瀹炽倰鍙娿伡銇欑敓娲诲粌妫勭墿銆傚粌闆绘睜銆佸粌鐏銆佸粌钖搧銆佸粌銉氥兂銈仺銇濄伄瀹瑰櫒銇仼銇屽惈銇俱倢銇俱仚銆�"),
+ "cat.hazardous.standard": ("1. 鏈夊鍨冨溇搴旇交鏀撅紝鏄撶牬鎹熺殑搴斿寘瑁瑰悗鎶曟斁\n2. 搴熺數姹犲簲淇濇寔瀹屾暣锛屼笉瑕佹媶瑙n3. 搴熺伅绠″簲闃叉鐮寸锛岀敤绾稿紶鍖呰9鍚庢姇鏀綷n4. 搴熻嵂鍝佸簲杩炲悓鍖呰涓�璧锋姇鏀綷n5. 搴熸补婕嗘《搴斿瘑灏佸悗鎶曟斁\n6. 鎶曟斁鏃跺簲娉ㄦ剰瀹夊叏锛岄伩鍏嶆硠婕廫n7. 濡傛槗鎸ュ彂锛岃瀵嗗皝鍚庢姇鏀�", "1. Handle hazardous waste gently; wrap fragile items.\n2. Keep batteries intact.\n3. Wrap light tubes to prevent breakage.\n4. Dispose medicine with packaging.\n5. Seal paint cans.\n6. Ensure safety, avoid leaks.\n7. Seal volatile items before disposal.", "1. 鞙犿暣 鞊半爤旮半姅 臧�氤嶊矊, 旯旮� 靿毚 瓴冹潃 臧愳嫺靹� 氚办稖頃橃劯鞖�.\n2. 韽愲鞍韯半Μ電� 攵勴暣頃橃 毵愱碃 鞓爠頃橁矊 鞙犾頃橃劯鞖�.\n3. 韽愲摫甏�鞚� 旯歆� 鞎婋弰搿� 膦呾澊搿� 臧愳嫺靹胳殧.\n4. 韽愳潣鞎巾拡鞚� 韽灔瓿� 頃粯 氚办稖頃橃劯鞖�.\n5. 韽愴帢鞚疙姼 韱奠潃 氚�氪夗晿靹胳殧.\n6. 鞎堨爠鞐� 鞙犾潣頃橁碃 雸勳稖鞚� 頂柬晿靹胳殧.\n7. 頊橂皽靹� 氍检鞚� 氚�氪� 頉� 氚办稖頃橃劯鞖�.", "1. 鏈夊銇斻伩銇唤銇忓叆銈屻�佸銈屻倓銇欍亜銈傘伄銇寘銈撱仹鎺掑嚭銇椼仸銇忋仩銇曘亜銆俓n2. 寤冮浕姹犮伅鍒嗚В銇涖仛銆佸畬鍏ㄣ仾鐘舵厠銈掍繚銇c仸銇忋仩銇曘亜銆俓n3. 寤冪伅绠°伅鍓层倢銇亜銈堛亞绱欍仹鍖呫倱銇ф帓鍑恒仐銇︺亸銇犮仌銇勩�俓n4. 寤冭柆鍝併伅鍖呰銇ㄤ竴绶掋伀鎺掑嚭銇椼仸銇忋仩銇曘亜銆俓n5. 寤冦儦銉炽偔缂躲伅瀵嗗皝銇椼仸銇忋仩銇曘亜銆俓n6. 瀹夊叏銇敞鎰忋仐銆佹紡銈屻倰閬裤亼銇︺亸銇犮仌銇勩�俓n7. 鎻櫤鎬с伄銈傘伄銇瘑灏併仐銇︽帓鍑恒仐銇︺亸銇犮仌銇勩��"),
+ "cat.wet": ("婀垮瀮鍦�", "Wet Waste", "鞀奠嫕 鞊半爤旮�", "婀裤仯銇熴仈銇�"),
+ "cat.wet.desc": ("鍗虫槗鑵愬瀮鍦俱�佹槗鑵愮殑鐢熸椿鐗╄川鍜岀敓娲诲簾寮冪墿銆備富瑕佸寘鎷細椋熸潗搴熸枡銆佸墿鑿滃墿楗�佽繃鏈熼鍝併�佺摐鐨灉鏍搞�佽姳鍗夌豢妞嶃�佷腑鑽嵂娓g瓑銆�", "Perishable household waste including food scraps, leftovers, expired food, fruit peels, flowers, and herbal dregs.", "攵�韺晿旮� 靿毚 靸濏櫆 氍检 氚� 韽愱赴氍�. 鞁濎灛耄� 彀岅杭旮�, 雮潃 鞚岇嫕, 鞙犿喌旮绊暅 歆�雮� 鞁濏拡, 瓿检澕 昊嶌路鞌�, 頇旍磮, 頃滌暯 彀岅杭旮� 霌膘澊 韽暔霅╇媹雼�.", "鑵愩倞銈勩仚銇勭敓娲荤墿璩兓鐢熸椿寤冩鐗┿�傞鏉愩亸銇氥�佹畫銈婄墿銆佹湡闄愬垏銈岄鍝併�佹灉鐗┿伄鐨兓鏍搞�佽姳銆佹饥鏂硅柆銇亱銇欍仾銇┿亴鍚伨銈屻伨銇欍��"),
+ "cat.wet.standard": ("1. 婀垮瀮鍦惧簲娌ュ共姘村垎鍚庢姇鏀綷n2. 绾祦璐ㄧ殑椋熺墿鍨冨溇锛屽鐗涘ザ绛夛紝搴旂洿鎺ュ�掑叆涓嬫按鍙n3. 鏈夊寘瑁呯墿鐨勬箍鍨冨溇搴斿皢鍖呰鐗╁幓闄ゅ悗鍒嗙被鎶曟斁\n4. 澶ч澶淬�佽礉澹崇被搴斾綔涓哄共鍨冨溇鎶曟斁\n5. 椁愬帹鍨冨溇搴斿幓闄ゆ潅鐗╁悗鎶曟斁", "1. Drain water before disposal.\n2. Pure liquids should go down the drain.\n3. Remove packaging from wet waste.\n4. Large bones and shells go in dry waste.\n5. Remove debris from kitchen waste.", "1. 氍缄赴毳� 鞝滉卑頃� 頉� 氚办稖頃橃劯鞖�.\n2. 靾滌垬 鞎§泊電� 頃橃垬甑棎 氩勲Μ靹胳殧.\n3. 韽灔鞚� 鞛堧姅 鞀奠嫕 鞊半爤旮半姅 韽灔鞚� 鞝滉卑頃橃劯鞖�.\n4. 韥� 爰�, 臁瓣皽昊嶌鞚� 瓯挫嫕 鞊半爤旮半 氚办稖頃橃劯鞖�.\n5. 鞚岇嫕氍� 鞊半爤旮半姅 鞚措歆堨潉 鞝滉卑頃橃劯鞖�.", "1. 姘村垏銈娿仐銇︺亱銈夋帓鍑恒仐銇︺亸銇犮仌銇勩�俓n2. 绱旂矉銇恫浣撱伅鎺掓按鍙c伀娴併仐銇︺亸銇犮仌銇勩�俓n3. 鍖呰銇屻亗銈嬫箍銇c仧銇斻伩銇寘瑁呫倰澶栥仐銇︺亸銇犮仌銇勩�俓n4. 澶с亶銇銆佽矟娈婚銇咕銇勩仧銇斻伩銇ㄣ仐銇︽帓鍑恒仐銇︺亸銇犮仌銇勩�俓n5. 鍘ㄤ綑銇斻伩銇暟鐗┿倰鍙栥倞闄ゃ亜銇︽帓鍑恒仐銇︺亸銇犮仌銇勩��"),
+ "cat.dry": ("骞插瀮鍦�", "Dry Waste", "瓯挫嫕 鞊半爤旮�", "涔俱亜銇熴仈銇�"),
+ "cat.dry.desc": ("闄ゅ彲鍥炴敹鐗┿�佹湁瀹冲瀮鍦俱�佹箍鍨冨溇浠ュ鐨勫叾浠栫敓娲诲簾寮冪墿銆�", "Other household waste that is not recyclable, hazardous, or wet waste.", "鞛櫆鞖╉拡, 鞙犿暣 鞊半爤旮�, 鞀奠嫕 鞊半爤旮� 鞕胳潣 旮绊儉 靸濏櫆 韽愱赴氍�.", "璩囨簮銇斻伩銆佹湁瀹炽仈銇裤�佹箍銇c仧銇斻伩浠ュ銇仢銇粬銇敓娲诲粌妫勭墿銆�"),
+ "cat.dry.standard": ("1. 灏介噺娌ュ共姘村垎鍚庢姇鏀綷n2. 闅句互杈ㄨ瘑绫诲埆鐨勭敓娲诲瀮鍦惧簲鎶曞叆骞插瀮鍦惧鍣╘n3. 浣撶Н杈冨ぇ鐨勫瀮鍦惧簲閫傚綋鍒嗚В鍚庢姇鏀綷n4. 涓�娆℃�ч鍏枫�佺焊宸剧瓑搴斾綔涓哄共鍨冨溇鎶曟斁\n5. 鐑熻拏搴斿畬鍏ㄧ唲鐏悗鎶曟斁", "1. Drain water when possible.\n2. Hard-to-classify waste goes in dry waste.\n3. Break down large items.\n4. Disposable utensils and tissues are dry waste.\n5. Extinguish cigarette butts completely.", "1. 臧�電ロ晿氅� 氍缄赴毳� 鞝滉卑頃橃劯鞖�.\n2. 攵勲臧� 鞏措牑鞖� 靸濏櫆 鞊半爤旮半姅 瓯挫嫕 鞊半爤旮办棎 氚办稖頃橃劯鞖�.\n3. 攵�頂缄皜 韥� 鞊半爤旮半姅 攵勴暣頃橃劯鞖�.\n4. 鞚柬殞鞖� 鞁濌赴, 頊挫電� 瓯挫嫕 鞊半爤旮办瀰雼堧嫟.\n5. 雼措鞍杲侅磮電� 鞕勳爠頌� 雭� 頉� 氚办稖頃橃劯鞖�.", "1. 銇с亶銈嬨仩銇戞按鍒囥倞銇椼仸銇忋仩銇曘亜銆俓n2. 鍒嗛銇岄洠銇椼亜鐢熸椿銇斻伩銇咕銇勩仧銇斻伩瀹瑰櫒銇叆銈屻仸銇忋仩銇曘亜銆俓n3. 浣撶銇ぇ銇嶃亜銇斻伩銇仼鍒囥伀鍒嗚В銇椼仸銇忋仩銇曘亜銆俓n4. 浣裤亜鎹ㄣ仸椋熷櫒銆併儐銈c儍銈枫儱銇咕銇勩仧銇斻伩銇с仚銆俓n5. 鍚搞亜娈汇伅瀹屽叏銇秷銇椼仸銇嬨倝鎺掑嚭銇椼仸銇忋仩銇曘亜銆�"),
+ "disposal.suggest.recyclable": ("鍙洖鏀剁墿", "Recyclables", "鞛櫆鞖╉拡", "璩囨簮銇斻伩"),
+ "disposal.line1.recyclable": ("璇蜂繚鎸佹竻娲佸共鐕ワ紝閬垮厤姹℃煋銆�", "Keep clean and dry to avoid contamination.", "旯仐頃橁碃 瓯挫“頃� 靸來儨搿� 鞓れ椉鞚� 頂柬暣 欤检劯鞖�.", "娓呮綌銇т咕鐕ャ仐銇熺姸鎱嬨倰淇濄仭銆佹睔鏌撱倰閬裤亼銇︺亸銇犮仌銇勩��"),
+ "disposal.line2.recyclable": ("鎶曟斁鍓嶈鍘婚櫎娈嬬暀鐗╋紝鍘嬫墎鍑忓銆�", "Remove residue and flatten before disposal.", "氚办稖 鞝� 鞛旍棳氍检潉 鞝滉卑頃橁碃 雸岆煬 攵�頂茧ゼ 欷勳棳 欤检劯鞖�.", "鎺掑嚭鍓嶃伀娈嬬疆鐗┿倰鍙栥倞闄ゃ亶銆佹桨銇椼仸瀹圭銈掓笡銈夈仐銇︺亸銇犮仌銇勩��"),
+ "disposal.tip1.recyclable": ("鍙洖鏀剁墿缁忓洖鏀跺鐞嗗悗锛屽彲閲嶆柊鍒舵垚鏂扮殑浜у搧锛岃妭绾﹁祫婧愩��", "Recyclables can be processed into new products, saving resources.", "鞛櫆鞖╉拡鞚� 鞛矘毽悩鞏� 靸堧鞖� 鞝滍拡鞙茧 毵岆摛鞏挫牳 鞛愳洂鞚� 鞝堨暯頃╇媹雼�.", "璩囨簮銇斻伩銇儶銈点偆銈儷鍑︾悊銇倛銈婃柊銇椼亜瑁藉搧銇啀鐢熴仌銈屻�佽硣婧愩倰绡�绱勩仐銇俱仚銆�"),
+ "disposal.tip2.recyclable": ("1涓鏂欑摱鍥炴敹鍚庡彲鑺傜渷瓒冲鐐逛寒60鐡︾伅娉�3灏忔椂鐨勭數鑳姐��", "Recycling one plastic bottle saves enough energy to power a 60W bulb for 3 hours.", "頂岆澕鞀ろ嫳氤� 1臧滊ゼ 鞛櫆鞖╉晿氅� 60W 鞝勱惮毳� 3鞁滉皠 旒� 靾� 鞛堧姅 鞝勲牓鞚� 鞝堨暯頃╇媹雼�.", "銉椼儵銈广儊銉冦偗銉溿儓銉�1鏈伄銉偟銈ゃ偗銉仹60W闆荤悆銈�3鏅傞枔鐐圭伅銇с亶銈嬮浕鍔涖倰绡�绱勩仹銇嶃伨銇欍��"),
+ "disposal.tip3.recyclable": ("鍥炴敹1鍚ㄥ簾绾稿彲鑺傜渷17妫垫爲銆�", "Recycling one ton of paper saves 17 trees.", "膦呾澊 1韱れ潉 鞛櫆鞖╉晿氅� 雮橂 17攴鸽(毳� 鞝堨暯頃� 靾� 鞛堨姷雼堧嫟.", "绱�1銉堛兂銇儶銈点偆銈儷銇�17鏈伄鏈ㄣ倰绡�绱勩仹銇嶃伨銇欍��"),
+ "disposal.tip4.recyclable": ("鍨冨溇鍒嗙被浠庣偣婊村仛璧凤紝璁╄祫婧愬惊鐜埄鐢ㄣ��", "Every small act of sorting helps the circular economy.", "鞛戩潃 攵勲 鞁れ矞鞚� 鞛愳洂 靾滍櫂鞐� 韥� 霃勳泙鞚� 霅╇媹雼�.", "銈淬儫鍒嗗垾銇皬銇曘仾瀹熻返銇嬨倝銆傝硣婧愩伄寰挵鍒╃敤銇仱銇亽銇俱仐銈囥亞銆�"),
+ "disposal.suggest.hazardous": ("鏈夊鍨冨溇", "Hazardous Waste", "鞙犿暣 鞊半爤旮�", "鏈夊銇斻伩"),
+ "disposal.line1.hazardous": ("璇疯交鏀撅紝鏄撶牬鎹熺殑搴斿寘瑁瑰悗鎶曟斁銆�", "Handle gently; wrap fragile items before disposal.", "臧�氤嶊矊 雱j碃, 旯旮� 靿毚 瓴冹潃 臧愳嫺靹� 氚办稖頃橃劯鞖�.", "杌姐亸鍏ャ倢銆佸銈屻倓銇欍亜銈傘伄銇寘銈撱仹鎺掑嚭銇椼仸銇忋仩銇曘亜銆�"),
+ "disposal.line2.hazardous": ("搴熺數姹犮�佸簾鐏绛夊簲淇濇寔瀹屾暣锛屼笉瑕佹媶瑙c��", "Batteries and light tubes should remain intact.", "韽愲鞍韯半Μ, 韽愲摫甏� 霌膘潃 攵勴暣頃橃 毵愱碃 鞓爠頃橁矊 鞙犾頃橃劯鞖�.", "寤冮浕姹犮�佸粌鐏銇仼銇垎瑙c仜銇氥�佸畬鍏ㄣ仾鐘舵厠銈掍繚銇c仸銇忋仩銇曘亜銆�"),
+ "disposal.tip1.hazardous": ("鏈夊鍨冨溇鍚湁瀵逛汉浣撳仴搴锋垨鐜鏈夊鐨勭墿璐紝闇�鐗规畩澶勭悊銆�", "Hazardous waste contains harmful substances requiring special treatment.", "鞙犿暣 鞊半爤旮办棎電� 瓯搓皶瓿� 頇橁步鞐� 頃措鞖� 氍检鞚� 韽暔霅橃柎 韸闺硠 觳橂Μ臧� 頃勳殧頃╇媹雼�.", "鏈夊銇斻伩銇伅鍋ュ悍銈勭挵澧冦伀鏈夊銇墿璩亴鍚伨銈屻�佺壒鍒ャ仾鍑︾悊銇屽繀瑕併仹銇欍��"),
+ "disposal.tip2.hazardous": ("1鑺傚簾鐢垫睜闅忔剰涓㈠純锛屽彲鑳芥薄鏌�1骞虫柟绫冲湡鍦�50骞淬��", "One discarded battery can contaminate 1 m虏 of land for 50 years.", "韽愲鞍韯半Μ 1臧滊ゼ 氍挫瀾鞙勲 氩勲Μ氅� 1銕� 韱犾枒鞚� 50雲勱皠 鞓れ椉鞁滍偓 靾� 鞛堨姷雼堧嫟.", "寤冮浕姹�1鍊嬨倰鐒¢�犱綔銇崹銇︺倠銇�1銕°伄鍦熷湴銈�50骞撮枔姹氭煋銇欍倠鍙兘鎬с亴銇傘倞銇俱仚銆�"),
+ "disposal.tip3.hazardous": ("搴熻崸鍏夌伅绠″惈鏈夋睘锛岀牬纰庡悗浼氭薄鏌撶┖姘斿拰鍦熷¥銆�", "Fluorescent tubes contain mercury; breakage pollutes air and soil.", "韽愴槙甏戨摫鞐愲姅 靾橃潃鞚� 霌れ柎 鞛堨柎 旯氅� 瓿店赴鞕� 韱犾枒鞚� 鞓れ椉鞁滍偟雼堧嫟.", "寤冭泹鍏夌伅绠°伀銇按閵�銇屽惈銇俱倢銆佸壊銈屻倠銇ㄧ┖姘椼仺鍦熷銈掓睔鏌撱仐銇俱仚銆�"),
+ "disposal.tip4.hazardous": ("姝g‘鎶曟斁鏈夊鍨冨溇锛屼繚鎶ゆ垜浠殑鍋ュ悍涓庣幆澧冦��", "Proper disposal protects our health and environment.", "鞓皵毳� 鞙犿暣 鞊半爤旮� 氚办稖鞚� 瓯搓皶瓿� 頇橁步鞚� 氤错樃頃╇媹雼�.", "鏈夊銇斻伩銈掓銇椼亸鎺掑嚭銇欍倠銇撱仺銇с�佸仴搴枫仺鐠板銈掑畧銈娿伨銇欍��"),
+ "disposal.suggest.wet": ("婀垮瀮鍦�", "Wet Waste", "鞀奠嫕 鞊半爤旮�", "婀裤仯銇熴仈銇�"),
+ "disposal.line1.wet": ("璇锋播骞叉按鍒嗗悗鎶曟斁锛岀函娴佽川搴斿�掑叆涓嬫按鍙c��", "Drain water before disposal; pour pure liquids down the drain.", "氍缄赴毳� 鞝滉卑頃� 頉� 氚办稖頃橁碃, 靾滌垬 鞎§泊電� 頃橃垬甑棎 氩勲Μ靹胳殧.", "姘村垏銈娿仐銇︺亱銈夋帓鍑恒仐銆佺磾绮嬨仾娑蹭綋銇帓姘村彛銇祦銇椼仸銇忋仩銇曘亜銆�"),
+ "disposal.line2.wet": ("鏈夊寘瑁呯墿鐨勬箍鍨冨溇搴斿幓闄ゅ寘瑁呭悗鍒嗙被鎶曟斁銆�", "Remove packaging from wet waste before sorting.", "韽灔鞚� 鞛堧姅 鞀奠嫕 鞊半爤旮半姅 韽灔鞚� 鞝滉卑頃� 頉� 攵勲頃橃劯鞖�.", "鍖呰銇屻亗銈嬫箍銇c仧銇斻伩銇寘瑁呫倰澶栥仐銇︺亱銈夊垎鍒ャ仐銇︺亸銇犮仌銇勩��"),
+ "disposal.tip1.wet": ("婀垮瀮鍦剧粡鐢熷寲澶勭悊鍚庡彲杞寲涓烘湁鏈鸿偉鏂欍��", "Wet waste can be composted into organic fertilizer.", "鞀奠嫕 鞊半爤旮半姅 靸濏檾頃� 觳橂Μ毳� 韱淀暣 鞙犼赴 牍勲搿� 鞝勴櫂霅� 靾� 鞛堨姷雼堧嫟.", "婀裤仯銇熴仈銇裤伅鐢熷寲瀛﹀嚘鐞嗐伀銈堛倞鏈夋鑲ユ枡銇虎鎻涖仹銇嶃伨銇欍��"),
+ "disposal.tip2.wet": ("涓婃捣姣忓ぉ浜х敓鐨勬箍鍨冨溇绾�1涓囧惃锛屾纭垎绫绘剰涔夐噸澶с��", "Shanghai generates about 10,000 tons of wet waste daily.", "靸來晿鞚措姅 頃橂( 鞎� 1毵� 韱れ潣 鞀奠嫕 鞊半爤旮半ゼ 氚办稖頃╇媹雼�. 鞓皵毳� 攵勲臧� 欷戩殧頃╇媹雼�.", "涓婃捣銇с伅姣庢棩绱�1涓囥儓銉炽伄婀裤仯銇熴仈銇裤亴鐧虹敓銇椼伨銇欍�傛銇椼亜鍒嗗垾銇岄噸瑕併仹銇欍��"),
+ "disposal.tip3.wet": ("婀垮瀮鍦炬姇鏀惧墠搴斿敖閲忔播骞诧紝鍑忓皯娓楁护娑蹭骇鐢熴��", "Draining wet waste reduces leachate during processing.", "氚办稖 鞝� 氍缄赴毳� 於╇秳頌� 鞝滉卑頃橂┐ 旃稖靾� 氚滌儩鞚� 欷勳澕 靾� 鞛堨姷雼堧嫟.", "鎺掑嚭鍓嶃伀姘村垏銈娿倰鍗佸垎銇銇嗐仺銆佹蹈鍑烘恫銇櫤鐢熴倰娓涖倝銇涖伨銇欍��"),
+ "disposal.tip4.wet": ("鍓╄彍鍓╅キ鍙樺簾涓哄疂锛屽姪鍔涜祫婧愬惊鐜埄鐢ㄣ��", "Food scraps can become valuable resources through composting.", "鞚岇嫕 彀岅杭旮半弰 鞛愳洂 靾滍櫂鞚� 靻岇頃� 鞛臧� 霅� 靾� 鞛堨姷雼堧嫟.", "娈嬨倞鐗┿倐璩囨簮寰挵銇泊閲嶃仾鏉愭枡銇仾銈娿伨銇欍��"),
+ "disposal.suggest.dry": ("骞插瀮鍦�", "Dry Waste", "瓯挫嫕 鞊半爤旮�", "涔俱亜銇熴仈銇�"),
+ "disposal.line1.dry": ("璇峰敖閲忔播骞叉按鍒嗗悗鎶曟斁銆�", "Drain water when possible before disposal.", "臧�電ロ晿氅� 氍缄赴毳� 鞝滉卑頃� 頉� 氚办稖頃橃劯鞖�.", "銇с亶銈嬨仩銇戞按鍒囥倞銇椼仸銇嬨倝鎺掑嚭銇椼仸銇忋仩銇曘亜銆�"),
+ "disposal.line2.dry": ("闅句互杈ㄨ瘑绫诲埆鐨勭敓娲诲瀮鍦惧簲鎶曞叆骞插瀮鍦俱��", "Hard-to-classify waste should go in dry waste.", "攵勲臧� 鞏措牑鞖� 靸濏櫆 鞊半爤旮半姅 瓯挫嫕 鞊半爤旮办棎 氚办稖頃橃劯鞖�.", "鍒嗛銇岄洠銇椼亜鐢熸椿銇斻伩銇咕銇勩仧銇斻伩銇叆銈屻仸銇忋仩銇曘亜銆�"),
+ "disposal.tip1.dry": ("骞插瀮鍦句富瑕侀�氳繃鐒氱儳鎴栧~鍩嬫柟寮忓鐞嗐��", "Dry waste is mainly processed by incineration or landfill.", "瓯挫嫕 鞊半爤旮半姅 欤茧 靻岅皝 霕愲姅 毵る鞙茧 觳橂Μ霅╇媹雼�.", "涔俱亜銇熴仈銇裤伅涓汇伀鐒煎嵈銇俱仧銇煁绔嬨仹鍑︾悊銇曘倢銇俱仚銆�"),
+ "disposal.tip2.dry": ("鍑忓皯骞插瀮鍦句骇鐢燂紝浠庢簮澶村仛濂藉瀮鍦惧垎绫汇��", "Reduce dry waste at the source through better sorting.", "瓯挫嫕 鞊半爤旮半ゼ 欷勳澊霠る┐ 攵勲毳� 靸濏櫆頇旐晿電� 瓴冹澊 欷戩殧頃╇媹雼�.", "涔俱亜銇熴仈銇裤倰娓涖倝銇欍伀銇�佸垎鍒ャ倰鐢熸椿鍖栥仚銈嬨亾銇ㄣ亴閲嶈銇с仚銆�"),
+ "disposal.tip3.dry": ("绾稿肪銆佺儫钂傘�佷竴娆℃�ч鍏风瓑閮藉睘浜庡共鍨冨溇銆�", "Tissues, cigarette butts, and disposable utensils are dry waste.", "頊挫, 雼措鞍杲侅磮, 鞚柬殞鞖� 鞁濌赴 霌膘潃 瓯挫嫕 鞊半爤旮办瀰雼堧嫟.", "銉嗐偅銉冦偡銉ャ�佸惛銇勬銆佷娇銇勬崹銇﹂鍣ㄣ仾銇┿伅涔俱亜銇熴仈銇裤仹銇欍��"),
+ "disposal.tip4.dry": ("鍨冨溇鍒嗙被锛岃鍩庡競鏇寸編涓姐��", "Better sorting makes our city more beautiful.", "鞊半爤旮� 攵勲搿� 雿� 鞎勲雼れ毚 霃勳嫓毳� 毵岆摛鞏� 臧戩嫓雼�.", "銈淬儫鍒嗗垾銇с�併倛銈婄編銇椼亜閮藉競銈掍綔銈娿伨銇椼倗銇嗐��"),
+ }
+ if key in UI:
+ return UI[key][lang_index]
+ return zh_val
+
+def main():
+ base_zh = load_zh_base()
+ items = build_items()
+
+ # Update zh.json items
+ new_zh = {k: v for k, v in base_zh.items() if not k.startswith("item.")}
+ new_zh["lang.ja"] = "鏃ユ湰瑾�"
+ for item in items:
+ suffix = item["nameKey"][5:]
+ new_zh[item["nameKey"]] = TRANSLATIONS[suffix][0]
+
+ with open(os.path.join(BASE, "config", "items.json"), "w", encoding="utf-8") as f:
+ json.dump(items, f, ensure_ascii=False, indent=2)
+ f.write("\n")
+
+ with open(os.path.join(BASE, "config", "i18n", "zh.json"), "w", encoding="utf-8") as f:
+ json.dump(new_zh, f, ensure_ascii=False, indent=2)
+ f.write("\n")
+
+ for lang, idx, fname in [("en", 1, "en.json"), ("ko", 2, "ko.json"), ("ja", 3, "ja.json")]:
+ lang_data = build_lang_file(new_zh, idx)
+ with open(os.path.join(BASE, "config", "i18n", fname), "w", encoding="utf-8") as f:
+ json.dump(lang_data, f, ensure_ascii=False, indent=2)
+ f.write("\n")
+
+ print(f"Generated {len(items)} items")
+ print(f"Recyclable: {len(RECYCLABLE)}, Hazardous: {len(HAZARDOUS)}, Wet: {len(WET)}, Dry: {len(DRY)}")
+
+ # verify all names mapped
+ all_names = RECYCLABLE + HAZARDOUS + WET + DRY
+ missing = [n for n in all_names if n not in ZH_TO_KEY]
+ if missing:
+ print("WARNING missing translations:", missing)
+
+if __name__ == "__main__":
+ main()
--
Gitblit v1.9.1