Browse Source

change i18n

master
godo 11 months ago
parent
commit
660f527e85
  1. 1
      frontend/package.json
  2. 40
      frontend/pnpm-lock.yaml
  3. 4
      frontend/src/components/builtin/EditFileName.vue
  4. 6
      frontend/src/components/builtin/EditType.vue
  5. 2
      frontend/src/components/builtin/FileIcon.vue
  6. 30
      frontend/src/components/builtin/FileList.vue
  7. 24
      frontend/src/components/builtin/FileProps.vue
  8. 2
      frontend/src/components/builtin/FileTree.vue
  9. 14
      frontend/src/components/builtin/FileViewer.vue
  10. 10
      frontend/src/components/builtin/Store.vue
  11. 14
      frontend/src/components/computer/Computer.vue
  12. 22
      frontend/src/components/computer/QuickLink.vue
  13. 12
      frontend/src/components/computer/UpPopover.vue
  14. 20
      frontend/src/components/setting/SetAccount.vue
  15. 20
      frontend/src/components/setting/SetCustom.vue
  16. 36
      frontend/src/components/setting/SetLang.vue
  17. 14
      frontend/src/components/setting/SetSystem.vue
  18. 50
      frontend/src/components/setting/SetUpdate.vue
  19. 22
      frontend/src/components/setting/Setting.vue
  20. 4
      frontend/src/components/taskbar/Magnet.vue
  21. 16
      frontend/src/components/taskbar/StartOption.vue
  22. 35
      frontend/src/hook/useContextMenu.ts
  23. 63
      frontend/src/i18n/index.ts
  24. 134
      frontend/src/i18n/lang/en.json
  25. 134
      frontend/src/i18n/lang/zh.json
  26. 153
      frontend/src/i18n/system/en.ts
  27. 158
      frontend/src/i18n/system/zh.ts
  28. 2
      frontend/src/main.ts
  29. 2
      frontend/src/system/config.ts
  30. 14
      frontend/src/system/core/Path.ts
  31. 2
      frontend/src/system/index.ts
  32. 10
      frontend/src/system/initBuiltin.ts
  33. 2
      frontend/src/system/window/Dialog.ts
  34. 3
      libs/dir.go
  35. 31
      localchat/client.go
  36. 30
      localchat/file.go
  37. 46
      localchat/server.go
  38. 3
      localchat/upload.go
  39. 63
      localchat/windiscovery.go
  40. 32
      progress/start.go

1
frontend/package.json

@ -21,6 +21,7 @@
"pinia-plugin-persist": "^1.0.0",
"vditor": "^3.10.4",
"vue": "^3.4.31",
"vue-i18n": "^9.13.1",
"vue-router": "^4.4.0",
"vue-web-screen-shot": "^1.5.3"
},

40
frontend/pnpm-lock.yaml

@ -44,6 +44,9 @@ importers:
vue:
specifier: ^3.4.31
version: 3.4.31(typescript@5.5.3)
vue-i18n:
specifier: ^9.13.1
version: 9.13.1(vue@3.4.31(typescript@5.5.3))
vue-router:
specifier: ^4.4.0
version: 4.4.0(vue@3.4.31(typescript@5.5.3))
@ -260,6 +263,18 @@ packages:
'@floating-ui/utils@0.2.4':
resolution: {integrity: sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==}
'@intlify/core-base@9.13.1':
resolution: {integrity: sha512-+bcQRkJO9pcX8d0gel9ZNfrzU22sZFSA0WVhfXrf5jdJOS24a+Bp8pozuS9sBI9Hk/tGz83pgKfmqcn/Ci7/8w==}
engines: {node: '>= 16'}
'@intlify/message-compiler@9.13.1':
resolution: {integrity: sha512-SKsVa4ajYGBVm7sHMXd5qX70O2XXjm55zdZB3VeMFCvQyvLew/dLvq3MqnaIsTMF1VkkOb9Ttr6tHcMlyPDL9w==}
engines: {node: '>= 16'}
'@intlify/shared@9.13.1':
resolution: {integrity: sha512-u3b6BKGhE6j/JeRU6C/RL2FgyJfy6LakbtfeVF8fJXURpZZTzfh3e05J0bu0XPw447Q6/WUp3C4ajv4TMS4YsQ==}
engines: {node: '>= 16'}
'@jridgewell/gen-mapping@0.3.5':
resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
engines: {node: '>=6.0.0'}
@ -950,6 +965,12 @@ packages:
'@vue/composition-api':
optional: true
vue-i18n@9.13.1:
resolution: {integrity: sha512-mh0GIxx0wPtPlcB1q4k277y0iKgo25xmDPWioVVYanjPufDBpvu5ySTjP5wOrSvlYQ2m1xI+CFhGdauv/61uQg==}
engines: {node: '>= 16'}
peerDependencies:
vue: ^3.0.0
vue-router@4.4.0:
resolution: {integrity: sha512-HB+t2p611aIZraV2aPSRNXf0Z/oLZFrlygJm+sZbdJaW6lcFqEDQwnzUBXn+DApw+/QzDU/I9TeWx9izEjTmsA==}
peerDependencies:
@ -1093,6 +1114,18 @@ snapshots:
'@floating-ui/utils@0.2.4': {}
'@intlify/core-base@9.13.1':
dependencies:
'@intlify/message-compiler': 9.13.1
'@intlify/shared': 9.13.1
'@intlify/message-compiler@9.13.1':
dependencies:
'@intlify/shared': 9.13.1
source-map-js: 1.2.0
'@intlify/shared@9.13.1': {}
'@jridgewell/gen-mapping@0.3.5':
dependencies:
'@jridgewell/set-array': 1.2.1
@ -1787,6 +1820,13 @@ snapshots:
dependencies:
vue: 3.4.31(typescript@5.5.3)
vue-i18n@9.13.1(vue@3.4.31(typescript@5.5.3)):
dependencies:
'@intlify/core-base': 9.13.1
'@intlify/shared': 9.13.1
'@vue/devtools-api': 6.6.3
vue: 3.4.31(typescript@5.5.3)
vue-router@4.4.0(vue@3.4.31(typescript@5.5.3)):
dependencies:
'@vue/devtools-api': 6.6.3

4
frontend/src/components/builtin/EditFileName.vue

@ -1,7 +1,7 @@
<template>
<div class="outer">
<input class="win-input" v-model="name" />
<WinButton @click="confirm">{{ i18n("confirm") }}</WinButton>
<WinButton @click="confirm">{{ t("confirm") }}</WinButton>
</div>
</template>
<script setup lang="ts">
@ -14,7 +14,7 @@ import { emitEvent } from "@/system/event";
// import { basename } from '@/system/core/Path';
import {
Dialog,
i18n,
t,
Notify,
basename,
join,

6
frontend/src/components/builtin/EditType.vue

@ -1,7 +1,7 @@
<template>
<div class="outer">
<input class="win-input" v-model="type" />
<WinButton @click="confirm">{{ i18n('confirm') }}</WinButton>
<WinButton @click="confirm">{{ t('confirm') }}</WinButton>
</div>
</template>
<script setup lang="ts">
@ -11,8 +11,8 @@ import { inject, ref } from 'vue';
// import { BrowserWindow } from '../window/BrowserWindow';
import { emitEvent } from '../../system/event';
// import { basename, extname } from '../core/Path';
// import { i18n } from '@/i18n';
import { i18n,basename,extname,BrowserWindow,useSystem,OsFileWithoutContent } from '../../system';
// import { t } from '@/i18n';
import { t,basename,extname,BrowserWindow,useSystem,OsFileWithoutContent } from '../../system';
const browserWindow: BrowserWindow = inject('browserWindow')!;
const fileBaseName = basename((browserWindow.config.content as OsFileWithoutContent).path);
const type = ref(extname(fileBaseName));

2
frontend/src/components/builtin/FileIcon.vue

@ -11,7 +11,7 @@
</template>
<script setup lang="ts">
import lnicon from '@/assets/ln.png';
import { OsFileWithoutContent,extname } from '../../system';
import { OsFileWithoutContent,extname } from '@/system';
// import { extname } from '../core/Path';
import { ref } from 'vue';
const props:any = defineProps<{

30
frontend/src/components/builtin/FileList.vue

@ -4,16 +4,16 @@
<div class="file-item_img"></div>
<div class="file-item_title"></div>
<div class="file-item_type">
<span>{{ i18n("size") }}</span>
<span>{{ t("size") }}</span>
</div>
<div class="file-item_type">
<span>{{ i18n("creation.time") }}</span>
<span>{{ t("creation.time") }}</span>
</div>
<div class="file-item_type">
<span>{{ i18n("modification.time") }}</span>
<span>{{ t("modification.time") }}</span>
</div>
<div class="file-item_type">
<span>{{ i18n("permission") }}</span>
<span>{{ t("permission") }}</span>
</div>
</div>
</template>
@ -67,7 +67,7 @@
import { useSystem, basename, dirname, join, OsFileWithoutContent } from '@/system/index.ts';
import { emitEvent, mountEvent } from '@/system/event';
import { useContextMenu } from '@/hook/useContextMenu.ts';
import { i18n, dealSystemName } from '@/i18n';
import { t, dealSystemName } from '@/i18n';
import { useFileDrag } from '@/hook/useFileDrag';
import { useAppMenu } from '@/hook/useAppMenu';
import { onMounted, ref, markRaw } from 'vue';
@ -116,7 +116,7 @@ function getName(item: any) {
// console.log(name)
// console.log(item.path)
if (name.endsWith('.exe')) {
return i18n(name.replace('.exe', ""))
return t(name.replace('.exe', ""))
} else {
return name
}
@ -232,14 +232,14 @@ function handleRightClick(mouse: MouseEvent, item: OsFileWithoutContent, index:
// eslint-disable-next-line prefer-const
let menuArr = [
{
label: i18n('open'),
label: t('open'),
click: () => {
chosenIndexs.value = [];
props.onOpen(item);
},
},
// {
// label: i18n('open.with'),
// label: t('open.with'),
// click: () => {
// chosenIndexs.value = [];
// openWith(item);
@ -249,7 +249,7 @@ function handleRightClick(mouse: MouseEvent, item: OsFileWithoutContent, index:
];
if (choose.ifShow) {
menuArr.push({
label: i18n('selected'),
label: t('selected'),
click: () => {
const paths: any = []
chosenIndexs.value.forEach((index) => {
@ -277,7 +277,7 @@ function handleRightClick(mouse: MouseEvent, item: OsFileWithoutContent, index:
if (ext != 'exe') {
const fileMenus = [
{
label: i18n('rename'),
label: t('rename'),
click: () => {
editIndex.value = index;
editName.value = basename(item.path);
@ -285,7 +285,7 @@ function handleRightClick(mouse: MouseEvent, item: OsFileWithoutContent, index:
},
},
{
label: i18n('copy'),
label: t('copy'),
click: () => {
//if(["/","/B"].includes(item.path)) return;
copyFile(chosenIndexs.value.map((index) => props.fileList[index]));
@ -293,7 +293,7 @@ function handleRightClick(mouse: MouseEvent, item: OsFileWithoutContent, index:
},
},
{
label: i18n('delete'),
label: t('delete'),
click: async () => {
// await Promise.all(
// chosenIndexs.value.map((index) => {
@ -318,7 +318,7 @@ function handleRightClick(mouse: MouseEvent, item: OsFileWithoutContent, index:
const sysEndMenu = [
{
label: i18n('create.shortcut'),
label: t('create.shortcut'),
click: () => {
createLink(item.path)?.then(() => {
chosenIndexs.value = [];
@ -327,7 +327,7 @@ function handleRightClick(mouse: MouseEvent, item: OsFileWithoutContent, index:
},
},
{
label: i18n('props'),
label: t('props'),
click: () => {
chosenIndexs.value.forEach((index) => {
openPropsWindow(props.fileList[index].path);
@ -353,7 +353,7 @@ function handleDragLeave() {
hoverIndex.value = -1;
}
// function dealI18nName(name: string) {
// function dealtName(name: string) {
// return name;
// }
</script>

24
frontend/src/components/builtin/FileProps.vue

@ -2,7 +2,7 @@
<div class="outer">
<div class="tab">
<div class="tab-item">
{{ i18n("general") }}
{{ t("general") }}
</div>
</div>
<div class="content">
@ -18,45 +18,45 @@
</span>
<WinButton class="some-button" @click="editFileName">
{{ i18n("rename") }}
{{ t("rename") }}
</WinButton>
</div>
</div>
<div class="split-line"></div>
<div class="propitem">
<div class="propname">{{ i18n("file.type") }}</div>
<div class="propname">{{ t("file.type") }}</div>
<div class="propvalue">{{ extname(file?.path || "") }}</div>
</div>
<div class="propitem">
<div class="propname">{{ i18n("location") }}</div>
<div class="propname">{{ t("location") }}</div>
<div class="propvalue">{{ file?.path }}</div>
</div>
<div class="propitem">
<div class="propname">{{ i18n("size") }}</div>
<div class="propname">{{ t("size") }}</div>
<div class="propvalue">{{ dealSize(file?.size) }}</div>
</div>
<div class="propitem">
<div class="propname">{{ i18n("permission") }}</div>
<div class="propname">{{ t("permission") }}</div>
<div class="propvalue">{{ file?.mode?.toString(8) || "" }}</div>
</div>
<div class="propitem">
<div class="propname">{{ i18n("creation.time") }}</div>
<div class="propname">{{ t("creation.time") }}</div>
<div class="propvalue">{{ file?.birthtime?.toLocaleString?.() || "" }}</div>
</div>
<div class="propitem">
<div class="propname">{{ i18n("modification.time") }}</div>
<div class="propname">{{ t("modification.time") }}</div>
<div class="propvalue">{{ file?.mtime?.toLocaleString?.() || "" }}</div>
</div>
</div>
<div class="button-group">
<WinButton @click="confirm">
{{ i18n("confirm") }}
{{ t("confirm") }}
</WinButton>
<WinButton @click="confirm">
{{ i18n("cancel") }}
{{ t("cancel") }}
</WinButton>
</div>
</div>
@ -69,7 +69,7 @@ import {
OsFileWithoutContent,
basename,
extname,
i18n,
t,
} from "@/system";
import { dealSize } from "@/util/file";
@ -82,7 +82,7 @@ function confirm() {
function editFileName() {
const win = new BrowserWindow({
title: i18n("rename"),
title: t("rename"),
content: "EditFileName",
config: {
content: file,

2
frontend/src/components/builtin/FileTree.vue

@ -50,7 +50,7 @@
<script lang="ts" setup>
import { useSystem,OsFileWithoutContent,basename } from '@/system/index.ts';
import { onMounted, ref } from 'vue';
import { dealSystemName } from '@/i18n/index.ts';
import { dealSystemName } from '@/i18n';
const sys = useSystem();
type FileWithOpen = OsFileWithoutContent & {
isOpen?: boolean;

14
frontend/src/components/builtin/FileViewer.vue

@ -1,7 +1,7 @@
<template>
<div class="txt">
<div class="txt-upper">
<div class="txt-button" @click="handleButton">{{ i18n("file") }}(F)</div>
<div class="txt-button" @click="handleButton">{{ t("file") }}(F)</div>
<div class="txt-button" @click="changeFormat">{{ format }}</div>
</div>
<div class="txt-content">
@ -11,7 +11,7 @@
</template>
<script setup lang="ts">
import { inject, ref } from "vue";
import { useSystem, Notify, BrowserWindow, i18n, Menu } from "@/system";
import { useSystem, Notify, BrowserWindow, t, Menu } from "@/system";
// import { Menu } from '@/menu/Menu';
const browserWindow: BrowserWindow | undefined = inject("browserWindow");
@ -40,13 +40,13 @@ const system = useSystem();
function handleButton(e: MouseEvent) {
Menu.buildFromTemplate([
{
label: i18n("save"),
label: t("save"),
click: async () => {
const file = await system.fs.stat(browserWindow?.config.path);
if (!file) {
new Notify({
title: i18n("tips"),
content: i18n("file.not.exist"),
title: t("tips"),
content: t("file.not.exist"),
});
return;
}
@ -60,8 +60,8 @@ function handleButton(e: MouseEvent) {
}
new Notify({
title: i18n("tips"),
content: i18n("file.save.success"),
title: t("tips"),
content: t("file.save.success"),
});
},
},

10
frontend/src/components/builtin/Store.vue

@ -78,7 +78,7 @@
<script setup lang="ts">
import { inject, onMounted, ref } from "vue";
import { BrowserWindow, System, Dialog, vDragable } from "@/system";
import { i18n } from "@/i18n";
import { t } from "@/i18n";
import storeList from "@/assets/store.json";
const browserWindow: BrowserWindow = inject("browserWindow")!;
import { getSystemKey, setSystemKey } from "@/system/config";
@ -115,9 +115,9 @@ function install(item: any) {
`link::url::${item.url}::${item.icon}`
);
Dialog.showMessageBox({
message: i18n("install.success"),
message: t("install.success"),
type: "info",
buttons: [i18n("confirm")],
buttons: [t("confirm")],
});
installedList.value.push(item.name);
setCache();
@ -126,9 +126,9 @@ function install(item: any) {
function uninstall(item: any) {
sys.fs.unlink(`${sys._options.userLocation}Desktop/${item.name}.url`);
Dialog.showMessageBox({
message: i18n("uninstall.success"),
message: t("uninstall.success"),
type: "info",
buttons: [i18n("confirm")],
buttons: [t("confirm")],
});
delete installedList.value[installedList.value.indexOf(item.name)];
setCache();

14
frontend/src/components/computer/Computer.vue

@ -3,9 +3,9 @@
<div class="group">
<!-- <div class="button">文件</div> -->
<!-- <div class="button">计算机</div> -->
<div class="button" @click="backFolder()">{{ i18n("back") }}</div>
<div class="button" @click="backFolder()">{{ t("back") }}</div>
<!-- 查看 -->
<div class="button" @click="popoverChange()">{{ i18n("view") }}</div>
<div class="button" @click="popoverChange()">{{ t("view") }}</div>
<!-- <div class="button" @click="newFolder()">新建</div> -->
</div>
<div v-if="isPopoverView" class="up-pop">
@ -30,9 +30,9 @@
<el-icon :size="20" color="#137bd2">
<Platform />
</el-icon>
{{ i18n("desktop") }}
{{ t("desktop") }}
</div>
<div class="showName">{{ i18n("computer") }}</div>
<div class="showName">{{ t("computer") }}</div>
<FileTree
:chosen-path="chosenTreePath"
mode="list"
@ -87,7 +87,7 @@ import {
dirname,
Notify,
useSystem,
i18n,
t,
} from "@/system/index.ts";
import { useContextMenu } from "@/hook/useContextMenu";
import { emitEvent, mountEvent } from "@/system/event";
@ -280,13 +280,13 @@ function backgroundUp() {
}
/* ------------ 新建文件夹 ------------*/
const createInput = ref(i18n("new.folder"));
const createInput = ref(t("new.folder"));
const creating = ref(false);
function creatingEditEnd() {
if (creating.value) {
createFolder(createInput.value);
creating.value = false;
createInput.value = i18n("new.folder");
createInput.value = t("new.folder");
}
}
function onBackClick() {

22
frontend/src/components/computer/QuickLink.vue

@ -1,6 +1,6 @@
<template>
<div class="contaion">
<div class="showName">{{ i18n("favorite") }}</div>
<div class="showName">{{ t("favorite") }}</div>
<div
class="file-item mode-list"
@ -21,7 +21,7 @@
</div>
</template>
<script setup lang="ts">
import { i18n } from "@/i18n";
import { t } from "@/i18n";
const props = defineProps({
onOpen: {
type: Function,
@ -33,47 +33,47 @@ const props = defineProps({
const quickLinks = [
{
img: "word",
name: i18n("document"),
name: t("document"),
path: "/C/Users/Doc",
},
{
img: "excel",
name: i18n("excel"),
name: t("excel"),
path: "/C/Users/Execl",
},
{
img: "pptexe",
name: i18n("ppt"),
name: t("ppt"),
path: "/C/Users/PPT",
},
{
img: "markdown",
name: i18n("markdown"),
name: t("markdown"),
path: "/C/Users/Markdown",
},
{
img: "mindexe",
name: i18n("mindmap"),
name: t("mindmap"),
path: "/C/Users/Mind",
},
{
img: "baiban",
name: i18n("whiteBoard"),
name: t("whiteBoard"),
path: "/C/Users/Baiban",
},
{
img: "kanban",
name: i18n("board"),
name: t("board"),
path: "/C/Users/Kanban",
},
{
img: "gallery",
name: i18n("gallery"),
name: t("gallery"),
path: "/C/Users/Photo",
},
{
img: "music",
name: i18n("music"),
name: t("music"),
path: "/C/Users/Music",
},
];

12
frontend/src/components/computer/UpPopover.vue

@ -7,35 +7,35 @@
:class="{ chosen: chosenView == 'big' }"
@click="changeView('big')"
>
{{ i18n("large.icon") }}
{{ t("large.icon") }}
</div>
<div
class="up-pop-button"
:class="{ chosen: chosenView == 'middle' }"
@click="changeView('middle')"
>
{{ i18n("middle.icon") }}
{{ t("middle.icon") }}
</div>
<div
class="up-pop-button"
:class="{ chosen: chosenView == 'icon' }"
@click="changeView('icon')"
>
{{ i18n("small.icon") }}
{{ t("small.icon") }}
</div>
<div
class="up-pop-button"
:class="{ chosen: chosenView == 'list' }"
@click="changeView('list')"
>
{{ i18n("list") }}
{{ t("list") }}
</div>
<div
class="up-pop-button"
:class="{ chosen: chosenView == 'detail' }"
@click="changeView('detail')"
>
{{ i18n("detail.info") }}
{{ t("detail.info") }}
</div>
</div>
<div class="group-title">布局</div>
@ -43,7 +43,7 @@
</div>
</template>
<script setup lang="ts">
import { i18n } from "@/i18n";
import { t } from "@/i18n";
import { ref } from "vue";
const props = defineProps({
modelValue: {

20
frontend/src/components/setting/SetAccount.vue

@ -15,21 +15,21 @@
<div class="setting">
<div v-if="0 === activeIndex">
<div class="setting-item">
<h1 class="setting-title">{{ i18n('account.info') }}</h1>
<h1 class="setting-title">{{ t('account.info') }}</h1>
</div>
<div class="setting-item">
<label> {{ i18n('account') }} </label>
<el-input v-model="account.username" :placeholder="i18n('account')" clearable />
<label> {{ t('account') }} </label>
<el-input v-model="account.username" :placeholder="t('account')" clearable />
</div>
<div class="setting-item">
<label> {{ i18n('password') }} </label>
<el-input v-model="account.password" type="password" :placeholder="i18n('password')" clearable/>
<label> {{ t('password') }} </label>
<el-input v-model="account.password" type="password" :placeholder="t('password')" clearable/>
</div>
<div class="setting-item">
<label></label>
<el-button @click="submit" type="primary">
{{ i18n('confirm') }}
{{ t('confirm') }}
</el-button>
</div>
</div>
@ -42,10 +42,10 @@
// import WinSelect from '@/components/win/WinSelect.vue';
import { ref } from 'vue';
import { Dialog,i18n } from '@/system/index.ts';
import { Dialog,t } from '@/system/index.ts';
import { getSystemKey, setSystemKey } from '@/system/config'
const items = [i18n('account.info')];
const items = [t('account.info')];
const activeIndex = ref(0);
@ -63,8 +63,8 @@ async function submit() {
// localStorage.setItem('godoOS_password', password.value);
setSystemKey('account', account.value);
Dialog.showMessageBox({
message: i18n('save.success'),
title: i18n('account'),
message: t('save.success'),
title: t('account'),
type: 'info',
}).then(() => {
location.reload();

20
frontend/src/components/setting/SetCustom.vue

@ -14,7 +14,7 @@
</div>
<div class="setting">
<div class="setting-item">
<h1 class="setting-title">{{ i18n("background") }}</h1>
<h1 class="setting-title">{{ t("background") }}</h1>
</div>
<div class="setting-item">
<el-select v-model="config.background.type">
@ -53,7 +53,7 @@
<div class="setting-item">
<label> </label>
<el-button @click="submit" type="primary">
{{ i18n("confirm") }}
{{ t("confirm") }}
</el-button>
</div>
</div>
@ -63,16 +63,16 @@
<script lang="ts" setup>
import { getSystemConfig, setSystemConfig } from "@/system/config";
import { ref, toRaw } from "vue";
import { Dialog, i18n, useSystem } from "@/system";
import { Dialog, t, useSystem } from "@/system";
const sys = useSystem();
const items = [i18n("background")];
const items = [t("background")];
const desktopOptions = [
{
label: i18n("image"),
label: t("image"),
value: "image",
},
{
label: i18n("color"),
label: t("color"),
value: "color",
},
];
@ -86,8 +86,8 @@ async function submit() {
setSystemConfig(val);
config.value = val;
Dialog.showMessageBox({
message: i18n("save.success"),
title: i18n("wallpaper"),
message: t("save.success"),
title: t("wallpaper"),
type: "success",
}).then(() => {
//location.reload();
@ -109,8 +109,8 @@ const selectItem = (index: number) => {
// await system.setConfig("rootStyle", rootStyle);
// Dialog.showMessageBox({
// message: i18n("save.success"),
// title: i18n("style"),
// message: t("save.success"),
// title: t("style"),
// type: "info",
// });
// }

36
frontend/src/components/setting/SetLang.vue

@ -15,7 +15,7 @@
<div class="setting">
<div v-if="0 === activeIndex">
<div class="setting-item">
<h1 class="setting-title">{{ i18n("language") }}</h1>
<h1 class="setting-title">{{ t("language") }}</h1>
</div>
<div class="setting-item">
<label></label>
@ -27,27 +27,12 @@
:value="item.value"
/>
</el-select>
<!-- <WinSelect
v-model="modelvalue"
:options="[
{
label: '中文',
value: 'zh',
},
{
label: 'English',
value: 'en',
},
]"
:placeholder="i18n('please.select')"
>
</WinSelect> -->
</div>
<div class="setting-item">
<label></label>
<el-button @click="submit" type="primary">
{{ i18n("confirm") }}
{{ t("confirm") }}
</el-button>
</div>
</div>
@ -58,22 +43,24 @@
<script lang="ts" setup>
import { ref } from "vue";
import { Dialog } from "@/system";
import { i18n, currentLang, setLang } from "@/i18n";
import { t, getLang, setLang } from "@/i18n";
import { useI18n } from 'vue-i18n';
const { locale } = useI18n()
const langList = [
{
label: "中文",
value: "zh",
value: "zh-cn",
},
{
label: "English",
value: "en",
},
];
const items = [i18n("language")];
const items = [t("language")];
const activeIndex = ref(0);
const currentLang = getLang();
const modelvalue = ref(currentLang);
const selectItem = (index: number) => {
@ -82,12 +69,11 @@ const selectItem = (index: number) => {
async function submit() {
setLang(modelvalue.value);
locale.value = modelvalue.value;
Dialog.showMessageBox({
message: i18n("save.success"),
title: i18n("language"),
message: t("save.success"),
title: t("language"),
type: "info",
}).then(() => {
location.reload();
});
}
</script>

14
frontend/src/components/setting/SetSystem.vue

@ -47,7 +47,7 @@
<div class="setting-item">
<label></label>
<el-button @click="submitOsInfo" type="primary">
{{ i18n("confirm") }}
{{ t("confirm") }}
</el-button>
</div>
</div>
@ -90,7 +90,7 @@
<div class="setting-item">
<label></label>
<el-button @click="submitUserInfo" type="primary">
{{ i18n("confirm") }}
{{ t("confirm") }}
</el-button>
</div>
</div>
@ -117,7 +117,7 @@
<script lang="ts" setup>
import { inject, ref } from "vue";
import { Dialog, join, System, i18n } from "@/system";
import { Dialog, join, System, t } from "@/system";
import JSZip from "jszip";
import FileSaver from "file-saver";
import { getSystemConfig, setSystemConfig } from "@/system/config";
@ -219,8 +219,8 @@ function submitOsInfo() {
if (res.code === 0) {
setSystemConfig(saveData);
Dialog.showMessageBox({
message: i18n("save.success"),
title: i18n("language"),
message: t("save.success"),
title: t("language"),
type: "info",
}).then(() => {
location.reload();
@ -260,8 +260,8 @@ function submitUserInfo() {
}
setSystemConfig(saveData);
Dialog.showMessageBox({
message: i18n("save.success"),
title: i18n("language"),
message: t("save.success"),
title: t("language"),
type: "info",
});
}

50
frontend/src/components/setting/SetUpdate.vue

@ -16,39 +16,39 @@
<!-- <div v-if="0 === activeIndex">
<div class="setting-item">
<h1 class="setting-title">
{{ i18n('system.backup.and.import') }}
{{ t('system.backup.and.import') }}
</h1>
</div>
<div class="setting-item">
<label>
{{ i18n('export.system.status') }}
{{ t('export.system.status') }}
</label>
<WinButton @click="handleClick(0)">
{{ i18n('export') }}
{{ t('export') }}
</WinButton>
</div>
<div class="setting-item">
<label>
{{ i18n('import.status.file') }}
{{ t('import.status.file') }}
</label>
<textarea v-model="inputConfig" type="text"></textarea>
</div>
<div class="setting-item">
<label></label>
<WinButton @click="handleClick(1)">
{{ i18n('import') }}
{{ t('import') }}
</WinButton>
</div>
</div> -->
<div v-if="0 === activeIndex">
<div class="setting-item">
<h1 class="setting-title">
{{ i18n("system.version") }}
{{ t("system.version") }}
</h1>
</div>
<div class="setting-item">
<label>
{{ i18n("version") }}
{{ t("version") }}
</label>
<span>{{ version }}</span>
</div>
@ -61,12 +61,12 @@
import { ref } from "vue";
// import { useSystem } from '@/system';
// import { Dialog } from '@/dialog/Dialog';
import { i18n } from "@/i18n";
import { t } from "@/i18n";
import { getSystemKey } from "@/system/config";
// const system = useSystem();
const items = [
// i18n('backup'), // '',
i18n("version"), // '',
// t('backup'), // '',
t("version"), // '',
];
const version = getSystemKey("version");
const activeIndex = ref(0);
@ -82,28 +82,28 @@ const selectItem = (index: number) => {
// try {
// await navigator.clipboard.writeText(cfg!);
// Dialog.showMessageBox({
// title: i18n('export.config'),
// message: i18n('export.success.saved.to.clipboard'),
// title: t('export.config'),
// message: t('export.success.saved.to.clipboard'),
// type: 'info',
// buttons: [i18n('confirm')],
// buttons: [t('confirm')],
// });
// } catch (err) {
// Dialog.showMessageBox({
// title: i18n('export.config'),
// message: i18n('export.failed'),
// title: t('export.config'),
// message: t('export.failed'),
// type: 'error',
// buttons: [i18n('confirm')],
// buttons: [t('confirm')],
// });
// }
// } else if (num === 1) {
// //
// try {
// const req = await Dialog.showMessageBox({
// title: i18n('import.config'),
// title: t('import.config'),
// // message: ',?',
// message: i18n('import.config.will.cover.existing.files.continue'),
// message: t('import.config.will.cover.existing.files.continue'),
// type: 'warning',
// buttons: [i18n('confirm'), i18n('cancel')],
// buttons: [t('confirm'), t('cancel')],
// });
// if (req.response === 1) return;
// await system?.deserializeState(inputConfig.value);
@ -111,18 +111,18 @@ const selectItem = (index: number) => {
// system?.reboot();
// }, 10000);
// await Dialog.showMessageBox({
// title: i18n('import.success'),
// message: i18n('import.success.reboot.soon'),
// title: t('import.success'),
// message: t('import.success.reboot.soon'),
// type: 'warning',
// buttons: [i18n('confirm')],
// buttons: [t('confirm')],
// });
// system?.reboot();
// } catch (err) {
// Dialog.showMessageBox({
// title: i18n('import.config'),
// message: i18n('import.failed'),
// title: t('import.config'),
// message: t('import.failed'),
// type: 'error',
// buttons: [i18n('confirm')],
// buttons: [t('confirm')],
// });
// }
// }

22
frontend/src/components/setting/Setting.vue

@ -9,7 +9,7 @@
<div class="upbar-left">
<div class="back-arr" v-if="currentRouter !== 'main'" @click="back"></div>
<div class="upbar-text">
{{ i18n("setting") }}
{{ t("setting") }}
</div>
</div>
<div class="upbar-right">
@ -23,7 +23,7 @@
<div class="outer" v-if="currentRouter === 'main'">
<div class="uper_tab">
<div class="tab">
{{ i18n("windows.setting") }}
{{ t("windows.setting") }}
</div>
</div>
<div class="outer_main">
@ -59,7 +59,7 @@
import { inject, ref } from "vue";
import { BrowserWindow } from "@/system/window/BrowserWindow";
import { i18n } from "@/i18n";
import { t } from "@/i18n";
import { useSystem } from "@/system";
import { vDragable } from "@/system/window/MakeDragable";
import { vGlowing } from "@/util/glowingBorder";
@ -84,33 +84,33 @@ function openSet(key: string) {
const setList = ref([
{
key: "system",
title: i18n("system"),
title: t("system"),
desc: "存储、备份还原、用户角色",
// desc: i18n('brightness'),
// desc: t('brightness'),
icon: "system",
content: "SetSystem",
},
{
key: "custom",
title: i18n("personalization"),
desc: i18n("background.lockscreen.color"),
title: t("personalization"),
desc: t("background.lockscreen.color"),
icon: "personal",
content: "SetCustom",
},
{
key: "language",
title: i18n("time.and.language"),
desc: i18n("language"),
title: t("time.and.language"),
desc: t("language"),
icon: "language",
content: "SetLang",
},
{
key: "account",
title: i18n("account"),
desc: i18n("your.account"),
title: t("account"),
desc: t("your.account"),
icon: "account",
content: "SetAccount",
},

4
frontend/src/components/taskbar/Magnet.vue

@ -22,7 +22,7 @@ import { emitEvent } from "@/system/event";
import { basename } from "@/system/core/Path";
import { OsFileWithoutContent } from "@/system/core/FileSystem";
import { vGlowing } from "@/util/glowingBorder";
import { i18n } from "@/i18n/index";
import { t } from "@/i18n";
const { openapp, appList } = useAppOpen("magnet");
function handle(item: OsFileWithoutContent) {
@ -32,7 +32,7 @@ function handle(item: OsFileWithoutContent) {
function getName(item: any) {
const name = basename(item.path);
if (name.endsWith(".exe")) {
return i18n(name.replace(".exe", ""));
return t(name.replace(".exe", ""));
} else {
return name;
}

16
frontend/src/components/taskbar/StartOption.vue

@ -8,7 +8,7 @@
</svg>
</div>
<div class="s-option-button_title">
{{ i18n("startMenu.power") }}
{{ t("startMenu.power") }}
</div>
</div>
<div class="s-option-button" @click.stop="($ev) => handleClick(1, $ev)" v-glowing>
@ -18,7 +18,7 @@
</svg>
</div>
<div class="s-option-button_title">
{{ i18n("setting") }}
{{ t("setting") }}
</div>
</div>
</div>
@ -26,7 +26,7 @@
</template>
<script lang="ts" setup>
import { emitEvent } from "@/system/event";
import { useSystem, Dialog, i18n, Menu, BrowserWindow } from "@/system";
import { useSystem, Dialog, t, Menu, BrowserWindow } from "@/system";
import { vGlowing } from "@/util/glowingBorder";
const sys = useSystem();
@ -35,18 +35,18 @@ function handleClick(key: number, ev: MouseEvent) {
case 0:
Menu.buildFromTemplate([
{
label: i18n("startMenu.shutdown"),
label: t("startMenu.shutdown"),
click: () => {
emitEvent("system.shutdown");
},
},
{
label: i18n("startMenu.recover"),
label: t("startMenu.recover"),
click: () => {
Dialog.showMessageBox({
title: i18n("startMenu.recover"),
message: i18n("is.recover"),
buttons: [i18n("startMenu.recover"), i18n("cancel")],
title: t("startMenu.recover"),
message: t("is.recover"),
buttons: [t("startMenu.recover"), t("cancel")],
}).then((res) => {
//console.log(res)
if (res.response === -1) {

35
frontend/src/hook/useContextMenu.ts

@ -2,9 +2,8 @@ import * as fspath from '../system/core/Path';
import { useSystem } from '../system';
import { BrowserWindow } from '../system/window/BrowserWindow';
import { OsFileWithoutContent } from '../system/core/FileSystem';
import { i18n } from '../i18n';
import { t } from '../i18n';
import { Dialog } from '../system/window/Dialog';
// import { MenuItem } from '@/menu/MenuItem';
import { Menu } from '../system/menu/Menu';
import { uniqBy } from '../util/modash';
import { UnwrapNestedRefs } from 'vue';
@ -12,19 +11,19 @@ import { UnwrapNestedRefs } from 'vue';
export function createTaskbarIconContextMenu(e: MouseEvent, windowNode: UnwrapNestedRefs<BrowserWindow>) {
Menu.buildFromTemplate([
{
label: i18n('close'),
label: t('close'),
click: () => {
windowNode.close();
},
},
{
label: i18n('maximize'),
label: t('maximize'),
click: () => {
windowNode.maximize();
},
},
{
label: i18n('minimize'),
label: t('minimize'),
click: () => {
windowNode.minimize();
},
@ -48,7 +47,7 @@ function useContextMenu() {
//console.log(path)
let menuArr = [
{
label: i18n('refresh'),
label: t('refresh'),
click: () => {
callback?.();
},
@ -151,7 +150,7 @@ function useContextMenu() {
// ],
// },
{
label: i18n('paste'),
label: t('paste'),
click: () => {
pasteFile(path).then(() => {
callback?.();
@ -159,7 +158,7 @@ function useContextMenu() {
},
},
{
label: i18n('new.folder'),
label: t('new.folder'),
click: () => {
createNewDir(path).then(() => {
callback?.();
@ -177,7 +176,7 @@ function useContextMenu() {
);
menu.popup(e);
}
async function createNewFile(path: string, ext: string = '.txt', title: string = i18n('new.file')) {
async function createNewFile(path: string, ext: string = '.txt', title: string = t('new.file')) {
const system = useSystem();
if (!system) return;
if (["/", "/B"].includes(path)) return;
@ -196,20 +195,20 @@ function useContextMenu() {
const system = useSystem();
if (!system) return;
if (["/", "/B"].includes(path)) return;
let newFilePath = fspath.join(path, i18n('new.folder'));
let newFilePath = fspath.join(path, t('new.folder'));
if (await system.fs.exists(newFilePath)) {
let i = 1;
while (await system.fs.exists(fspath.join(path, `${i18n('new.folder')}(${i})`))) {
while (await system.fs.exists(fspath.join(path, `${t('new.folder')}(${i})`))) {
i++;
}
newFilePath = fspath.join(path, `${i18n('new.folder')}(${i})`);
newFilePath = fspath.join(path, `${t('new.folder')}(${i})`);
}
return await system.fs.mkdir(newFilePath);
}
function openPropsWindow(path: string) {
new BrowserWindow({
title: i18n('props'),
title: t('props'),
content: "FileProps",
config: {
content: path,
@ -316,7 +315,7 @@ function useContextMenu() {
}
async function openWith(file: OsFileWithoutContent) {
const tempWin = new BrowserWindow({
title: i18n('open.with'),
title: t('open.with'),
content: "OpenWiteDialog",
config: {
content: file.path,
@ -375,8 +374,8 @@ function useContextMenu() {
if (["/", "/B"].includes(path)) return;
if (fspath.extname(path) === '.ln') {
Dialog.showMessageBox({
title: i18n('error'),
message: i18n('cannot.create.shortcut'),
title: t('error'),
message: t('cannot.create.shortcut'),
type: 'error',
});
return;
@ -386,8 +385,8 @@ function useContextMenu() {
const linkPath = fspath.join(parentPath, baseName + '.ln');
if (await system.fs.exists(linkPath)) {
Dialog.showMessageBox({
title: i18n('error'),
message: i18n('shortcut.has.been.created'),
title: t('error'),
message: t('shortcut.has.been.created'),
type: 'error',
});
return;

63
frontend/src/i18n/index.ts

@ -1,18 +1,21 @@
import { zhCN } from './system/zh';
import { enUS } from './system/en';
import { getSystemKey, setSystemKey } from '../system/config'
function getLang() {
import { createI18n } from 'vue-i18n'
import elEnLocale from 'element-plus/es/locale/lang/en'
import elZhLocale from 'element-plus/es/locale/lang/zh-cn'
import zhLang from './lang/zh.json';
import enLang from './lang/en.json';
import { getSystemKey, setSystemKey } from '@/system/config'
export function getLang() {
let currentLang = getSystemKey('lang')
if (!currentLang) {
try {
const supported = ["en", "zh"]
const { 0: browserLang } = navigator.language.split("-");
const supported = ["en", "zh-cn"]
const browserLang = (navigator.language || (navigator as any).browserLanguage).toLowerCase()
if (supported.includes(browserLang)) {
currentLang = browserLang
} else {
currentLang = "en";
}
setLang(currentLang)
} catch (e) {
console.log(e);
}
@ -20,28 +23,42 @@ function getLang() {
return currentLang
}
export let currentLang = getLang()
const messages = {
en: {
...enLang,
...elEnLocale
},
'zh-cn': {
...zhLang,
...elZhLocale
}
}
export const i18n = createI18n({
globalInjection: true,
legacy: false,
locale: getLang(),
messages: messages
})
export function setLang(lang: string) {
currentLang = lang
//currentLang = lang
setSystemKey('lang', lang)
}
export function i18n(key: string) {
if (currentLang == 'zh') {
return zhCN[key] ?? key;
} else if (currentLang == 'en') {
return enUS[key] ?? key;
} else {
return enUS[key] ?? key;
}
export function changeLang() {
const lang = getLang()
const setlang = lang == 'en' ? 'zh-cn' : 'en'
setLang(setlang)
return setlang
}
export function t(textkey :string) {
return i18n.global.t(textkey)
}
export function dealSystemName(name: string) {
const sysNames:any = {
"C": i18n('system'),
"D": i18n('document'),
"E": i18n('office'),
"B": i18n('recycle')
"C": t('system'),
"D": t('document'),
"E": t('office'),
"B": t('recycle')
}
if (sysNames[name]) {
return sysNames[name];

134
frontend/src/i18n/lang/en.json

@ -0,0 +1,134 @@
{
"hello": "hello",
"startMenu.power": "Power",
"setting": "Setting",
"startMenu.shutdown": "Shutdown",
"startMenu.recover": "Recover",
"windows.setting": "Windows Setting",
"system": "System",
"office": "Office",
"recycle": "Recycle",
"favorite": "Favorites",
"desktop": "Desktop",
"personalization": "Personalization",
"background.lockscreen.color": "Background, Color Theme",
"update.security": "Update & Security",
"windows.update.recover.backup": "Windows Update, Recovery, Backup",
"background": "Background",
"image": "Image",
"color": "Color",
"set.background": "Set Background",
"from.network": "From Network",
"from.string": "From String",
"please.select": "Please Select",
"confirm": "Confirm",
"cancel": "Cancel",
"system.version": "Version",
"save.success": "Save Success",
"wallpaper": "Wallpaper",
"system.backup.and.import": "System Backup & Import",
"export.system.status": "Export System Status",
"export.config": "Export Config",
"import.status.file": "Import Status File",
"import.config": "Import Config",
"export.success.saved.to.clipboard": "Export Success, Saved to Clipboard",
"import.config.will.cover.existing.files.continue": "Import Config will cover existing files, continue?",
"export.failed": "Export Failed",
"import.success": "Import Success",
"backup": "Backup",
"import.success.reboot.soon": "Import Success, Reboot Soon",
"import.failed": "Import Failed",
"import": "Import",
"export": "Export",
"refresh": "Refresh",
"new.file": "New File",
"new.folder": "New Folder",
"open": "Open",
"selected": "Selected",
"props": "Props",
"delete": "Delete",
"general": "General",
"rename": "Rename",
"create.shortcut": "Create Shortcut",
"file.type": "File Type",
"location": "Location",
"edit.type": "Edit Type",
"file": "File",
"save": "Save",
"alert": "Alert",
"tips": "Tips",
"file.not.exist": "File Not Exist",
"file.save.success": "File Save Success",
"new": "New",
"back": "Back",
"path.not.exist": "Path Not Exist",
"success": "Success",
"failed": "Failed",
"error": "Error",
"install": "Install",
"uninstall": "Uninstall",
"install.success": "Install Success",
"uninstall.success": "Uninstall Success",
"close": "Close",
"maximize": "Maximize",
"minimize": "Minimize",
"time": "Time",
"time.and.language": "Time and Language",
"and": "And",
"screen": "Screen",
"brightness": "Brightness",
"size": "Size",
"view": "View",
"permission": "Permission",
"modification.time": "Modification Time",
"creation.time": "Creation Time",
"large.icon": "Large Icon",
"middle.icon": "Middle Icon",
"small.icon": "Small Icon",
"list": "List",
"detail.info": "Detail Info",
"computer": "Computer",
"terminal": "Terminal",
"appstore": "App Store",
"board": "Board",
"document": "Document",
"excel": "Excel",
"markdown": "markdown",
"mindmap": "Mindmap",
"ppt": "Ppt",
"fileEditor": "FileEditor",
"todo": "Todo",
"whiteBoard": "WhiteBoard",
"piceditor": "PhotoEditor",
"gantt": "Gantt",
"browser": "Browser",
"aiSetting": "AI Setting",
"calculator": "Calculator",
"music": "Music",
"photo": "Photo",
"musicStore": "Music",
"gallery": "Gallery",
"video": "Video",
"PDF": "PDF Previewer",
"Terminal": "Terminal",
"calendar": "Calendar",
"localchat": "LocalChat",
"text.document": "Text Document",
"language": "Language",
"style": "Style",
"is.recover": "Is Recover?",
"version": "Version",
"account": "Account",
"password": "Password",
"your.account": "Your Account",
"account.info": "Account Info",
"copy": "Copy",
"paste": "Paste",
"open.with": "Open With",
"please.reboot": "Please Reboot",
"white": "White",
"black": "Black",
"cannot.create.shortcut": "Cannot Create Shortcut",
"shortcut.has.been.created": "Shortcut Has Been Created",
"system.message": "System Message"
}

134
frontend/src/i18n/lang/zh.json

@ -0,0 +1,134 @@
{
"hello": "你好",
"startMenu.power": "电源",
"startMenu.shutdown": "关机",
"startMenu.recover": "恢复",
"windows.setting": "系统设置",
"system": "系统",
"office": "办公",
"recycle": "回收站",
"favorite": "我的收藏",
"desktop": "桌面",
"personalization": "个性化",
"background.lockscreen.color": "背景,锁屏,颜色",
"update.security": "更新和安全",
"windows.update.recover.backup": "系统更新,恢复,备份",
"background": "背景",
"image": "图片",
"color": "颜色",
"set.background": "设置背景",
"from.network": "来源网络",
"from.string": "来源字符串",
"please.select": "请选择",
"confirm": "确认",
"cancel": "取消",
"system.version": "系统版本",
"save.success": "保存成功",
"wallpaper": "壁纸",
"system.backup.and.import": "系统备份和导入",
"export.system.status": "导出系统状态",
"export.config": "导出配置",
"import.status.file": "导入状态文件",
"import.config": "导入配置",
"export.success.saved.to.clipboard": "导出成功,已保存到粘贴板",
"import.config.will.cover.existing.files.continue": "导入配置将覆盖现有文件,是否继续?",
"export.failed": "导出失败",
"import.success": "导入成功",
"backup": "备份",
"import.success.reboot.soon": "导入成功,即将重启",
"import.failed": "导入失败",
"import": "导入",
"export": "导出",
"refresh": "刷新",
"new.file": "新建文件",
"new.folder": "新建文件夹",
"open": "打开",
"selected": "选中",
"props": "属性",
"delete": "删除",
"general": "常规",
"rename": "重命名",
"create.shortcut": "快捷方式",
"file.type": "文件类型",
"location": "位置",
"edit.type": "编辑类型",
"file": "文件",
"save": "保存",
"alert": "警告",
"tips": "提示",
"file.not.exist": "文件不存在",
"file.save.success": "文件保存成功",
"new": "新建",
"back": "返回",
"path.not.exist": "路径不存在",
"success": "成功",
"failed": "失败",
"error": "错误",
"install": "安装",
"uninstall": "卸载",
"install.success": "安装成功",
"uninstall.success": "卸载成功",
"close": "关闭",
"maximize": "最大化",
"minimize": "最小化",
"time": "时间",
"time.and.language": "时间和语言",
"and": "和",
"screen": "屏幕",
"brightness": "亮度",
"view": "查看",
"size": "大小",
"permission": "权限",
"modification.time": "修改时间",
"creation.time": "创建时间",
"large.icon": "大图标",
"middle.icon": "中图标",
"small.icon": "小图标",
"list": "列表",
"detail.info": "详细信息",
"computer": "此电脑",
"terminal": "终端",
"appstore": "应用商店",
"setting": "设置",
"board": "看板",
"document": "文档",
"excel": "表格",
"markdown": "markdown",
"mindmap": "思维导图",
"ppt": "演示文稿",
"fileEditor": "文件编辑器",
"todo": "待办",
"whiteBoard": "白板",
"piceditor": "图片编辑",
"gantt": "甘特图",
"browser": "浏览器",
"aiSetting": "AI设置",
"calculator": "计算器",
"music": "音乐",
"musicStore": "音乐库",
"photo": "图片",
"gallery": "图片库",
"video": "视频播放器",
"PDF": "PDF预览",
"Terminal": "Terminal",
"calendar": "日历",
"localchat": "内网聊天",
"text.document": "文本文档",
"language": "语言",
"style": "样式",
"is.recover": "是否恢复出厂设置?",
"version": "版本",
"account": "账户",
"password": "密码",
"your.account": "你的账户",
"account.info": "账户信息",
"copy": "复制",
"paste": "粘贴",
"open.with": "打开方式",
"please.reboot": "请重启",
"white": "白色",
"black": "黑色",
"cannot.create.shortcut": "无法创建快捷方式",
"shortcut.has.been.created": "快捷方式已创建",
"system.message": "系统消息"
}

153
frontend/src/i18n/system/en.ts

@ -1,153 +0,0 @@
export const enUS:any = {
hello: 'hello',
'startMenu.power': 'Power',
setting: 'Setting',
'startMenu.shutdown': 'Shutdown',
'startMenu.recover': 'Recover',
'windows.setting': 'Windows Setting',
system: 'System',
office: 'Office',
recycle: 'Recycle',
favorite: 'Favorites',
desktop: 'Desktop',
personalization: 'Personalization',
'background.lockscreen.color': 'Background, Color Theme',
'update.security': 'Update & Security',
'windows.update.recover.backup': 'Windows Update, Recovery, Backup',
background: 'Background',
image: 'Image',
color: 'Color',
'set.background': 'Set Background',
'from.network': 'From Network',
'from.string': 'From String',
'please.select': 'Please Select',
confirm: 'Confirm',
cancel: 'Cancel',
'system.version': 'Version',
'save.success': 'Save Success',
wallpaper: 'Wallpaper',
'system.backup.and.import': 'System Backup & Import',
'export.system.status': 'Export System Status',
'export.config': 'Export Config',
'import.status.file': 'Import Status File',
'import.config': 'Import Config',
'export.success.saved.to.clipboard': 'Export Success, Saved to Clipboard',
'import.config.will.cover.existing.files.continue': 'Import Config will cover existing files, continue?',
'export.failed': 'Export Failed',
'import.success': 'Import Success',
backup: 'Backup',
'import.success.reboot.soon': 'Import Success, Reboot Soon',
'import.failed': 'Import Failed',
import: 'Import',
export: 'Export',
refresh: 'Refresh',
'new.file': 'New File',
'new.folder': 'New Folder',
open: 'Open',
selected: 'Selected',
props: 'Props',
delete: 'Delete',
general: 'General',
rename: 'Rename',
'create.shortcut': 'Create Shortcut',
'file.type': 'File Type',
location: 'Location',
'edit.type': 'Edit Type',
file: 'File',
save: 'Save',
alert: 'Alert',
tips: 'Tips',
'file.not.exist': 'File Not Exist',
'file.save.success': 'File Save Success',
new: 'New',
back: 'Back',
'path.not.exist': 'Path Not Exist',
success: 'Success',
failed: 'Failed',
error: 'Error',
install: 'Install',
uninstall: 'Uninstall',
'install.success': 'Install Success',
'uninstall.success': 'Uninstall Success',
close: 'Close',
maximize: 'Maximize',
minimize: 'Minimize',
time: 'Time',
'time.and.language': 'Time and Language',
and: 'And',
screen: 'Screen',
brightness: 'Brightness',
size: 'Size',
view: 'View',
permission: 'Permission',
'modification.time': 'Modification Time',
'creation.time': 'Creation Time',
'large.icon': 'Large Icon',
'middle.icon': 'Middle Icon',
'small.icon': 'Small Icon',
list: 'List',
'detail.info': 'Detail Info',
computer: 'Computer',
terminal: 'Terminal',
appstore: 'App Store',
moduleMgr: 'AI Module',
aiChat: 'AI Chat',
aiSpeech:'AI Speech',
knowledge: 'Knowledge',
aiCreation: 'AI Creation',
aiHelper: 'AI Helper',
aiTrans: 'AI Translate',
aiRecording: 'AI Recording',
aiDraw: 'AI Draw',
board: 'Board',
document: 'Document',
excel: 'Excel',
markdown: 'markdown',
mindmap: 'Mindmap',
ppt: 'Ppt',
fileEditor: 'FileEditor',
todo: 'Todo',
whiteBoard: 'WhiteBoard',
piceditor: 'PhotoEditor',
gantt: 'Gantt',
browser: 'Browser',
aiSetting: 'AI Setting',
calculator: 'Calculator',
music: 'Music',
photo: 'Photo',
musicStore: 'Music',
gallery: 'Gallery',
video: 'Video',
PDF: 'PDF Previewer',
Terminal: 'Terminal',
calendar: 'Calendar',
localchat:'LocalChat',
'text.document': 'Text Document',
language: 'Language',
style: 'Style',
'is.recover': 'Is Recover?',
version: 'Version',
account: 'Account',
password: 'Password',
'your.account': 'Your Account',
'account.info': 'Account Info',
copy: 'Copy',
paste: 'Paste',
'open.with': 'Open With',
'please.reboot': 'Please Reboot',
white: 'White',
black: 'Black',
'cannot.create.shortcut': 'Cannot Create Shortcut',
'shortcut.has.been.created': 'Shortcut Has Been Created',
'system.message': 'System Message',
};

158
frontend/src/i18n/system/zh.ts

@ -1,158 +0,0 @@
export const zhCN:any = {
hello: '你好',
'startMenu.power': '电源',
'startMenu.shutdown': '关机',
'startMenu.recover': '恢复',
'windows.setting': '系统设置',
system: '系统',
office:'办公',
recycle:'回收站',
favorite:'我的收藏',
desktop:'桌面',
personalization: '个性化',
'background.lockscreen.color': '背景,锁屏,颜色',
'update.security': '更新和安全',
'windows.update.recover.backup': '系统更新,恢复,备份',
background: '背景',
image: '图片',
color: '颜色',
'set.background': '设置背景',
'from.network': '来源网络',
'from.string': '来源字符串',
'please.select': '请选择',
confirm: '确认',
cancel: '取消',
'system.version': '系统版本',
'save.success': '保存成功',
wallpaper: '壁纸',
'system.backup.and.import': '系统备份和导入',
'export.system.status': '导出系统状态',
'export.config': '导出配置',
'import.status.file': '导入状态文件',
'import.config': '导入配置',
'export.success.saved.to.clipboard': '导出成功,已保存到粘贴板',
'import.config.will.cover.existing.files.continue': '导入配置将覆盖现有文件,是否继续?',
'export.failed': '导出失败',
'import.success': '导入成功',
backup: '备份',
'import.success.reboot.soon': '导入成功,即将重启',
'import.failed': '导入失败',
import: '导入',
export: '导出',
refresh: '刷新',
'new.file': '新建文件',
'new.folder': '新建文件夹',
open: '打开',
selected:'选中',
props: '属性',
delete: '删除',
general: '常规',
rename: '重命名',
'create.shortcut': '快捷方式',
'file.type': '文件类型',
location: '位置',
'edit.type': '编辑类型',
file: '文件',
save: '保存',
alert: '警告',
tips: '提示',
'file.not.exist': '文件不存在',
'file.save.success': '文件保存成功',
new: '新建',
back: '返回',
'path.not.exist': '路径不存在',
success: '成功',
failed: '失败',
error: '错误',
install: '安装',
uninstall: '卸载',
'install.success': '安装成功',
'uninstall.success': '卸载成功',
close: '关闭',
maximize: '最大化',
minimize: '最小化',
time: '时间',
'time.and.language': '时间和语言',
and: '和',
screen: '屏幕',
brightness: '亮度',
view: '查看',
size: '大小',
permission: '权限',
'modification.time': '修改时间',
'creation.time': '创建时间',
'large.icon': '大图标',
'middle.icon': '中图标',
'small.icon': '小图标',
list: '列表',
'detail.info': '详细信息',
computer: '此电脑',
terminal: '终端',
appstore: '应用商店',
setting: '设置',
moduleMgr:'模型管理',
aiChat : 'AI对话',
aiSpeech: 'AI语音',
knowledge: '知识库',
aiCreation:'AI创作',
aiHelper:'AI助手',
aiTrans:'AI翻译',
aiRecording:'AI听录',
aiDraw:'AI绘图',
board:'看板',
document:'文档',
excel:'表格',
markdown:'markdown',
mindmap:'思维导图',
ppt:'演示文稿',
fileEditor:'文件编辑器',
todo:'待办',
whiteBoard:'白板',
piceditor:'图片编辑',
gantt:'甘特图',
browser:'浏览器',
aiSetting:'AI设置',
calculator:'计算器',
music:'音乐',
musicStore:'音乐库',
photo:'图片',
gallery:'图片库',
video:'视频播放器',
PDF:'PDF预览',
Terminal:'Terminal',
calendar:'日历',
localchat:'内网聊天',
'text.document': '文本文档',
language: '语言',
style: '样式',
'is.recover': '是否恢复出厂设置?',
version: '版本',
account: '账户',
password: '密码',
'your.account': '你的账户',
'account.info': '账户信息',
copy: '复制',
paste: '粘贴',
'open.with': '打开方式',
'please.reboot': '请重启',
white: '白色',
black: '黑色',
'cannot.create.shortcut': '无法创建快捷方式',
'shortcut.has.been.created': '快捷方式已创建',
'system.message': '系统消息',
};

2
frontend/src/main.ts

@ -7,10 +7,12 @@ import './assets/windows10.scss'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import router from './system/router'
import screenShort from "vue-web-screen-shot"
import {i18n} from './i18n/index.ts'
const app = createApp(App)
app.use(router)
app.use(ElementPlus)
app.use(pinia)
app.use(i18n)
app.use(screenShort, { enableWebRtc: true })
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {

2
frontend/src/system/config.ts

@ -20,7 +20,7 @@ export const getSystemConfig = (ifset = false) => {
config.isFirstRun = false;
}
if (!config.lang) {
config.lang = 'zh';
config.lang = '';
}
// 初始化API相关URL,若本地存储中已存在则不进行覆盖
if (!config.apiUrl) {

14
frontend/src/system/core/Path.ts

@ -499,17 +499,3 @@ export function isChildPath(parent: string, dir: string) {
return relativeRes && !relativeRes.startsWith('..') && !isAbsolute(relativeRes);
}
// export function dealI18nName(name: string) {
// const sysNames:any = {
// "C" : "系统",
// "D" : "文档",
// "E" : "办公",
// "B" : "回收站"
// }
// if(sysNames[name]) {
// return sysNames[name];
// }else{
// return name;
// }
// //return name;
// }

2
frontend/src/system/index.ts

@ -533,7 +533,7 @@ export { Dialog } from './window/Dialog';
export type { SystemOptions, WinApp } from './type/type';
export { vDragable } from './window/MakeDragable';
export type { OsFileInterface } from './core/FIleInterface';
export { i18n } from '../i18n';
export { t } from '../i18n';
export { Tray } from './menu/Tary';
export { dealIcon } from '../util/Icon';
export { Menu } from './menu/Menu';

10
frontend/src/system/initBuiltin.ts

@ -1,6 +1,6 @@
import type { System } from "./index";
import { BrowserWindow } from "./window/BrowserWindow";
import { i18n } from "../i18n";
import { t } from "@/i18n";
import { dealIcon } from "../util/Icon";
import { basename } from "./core/Path";
@ -15,7 +15,7 @@ export function initBuiltinApp(system: System) {
name: d.name,
icon: d.appIcon,
window: {
title: i18n(d.name),
title: t(d.name),
content: d.content,
icon: d.appIcon,
width: d.width,
@ -73,10 +73,10 @@ export function initBuiltinApp(system: System) {
if (d.isContext) {
system.setConfig("contextMenus", [
{
label: i18n(d.name),
label: t(d.name),
click() {
new BrowserWindow({
title: i18n(d.name),
title: t(d.name),
icon: d.appIcon,
path: addSave.window.path,
width: d.width,
@ -167,7 +167,7 @@ export function initBuiltinFileOpener(system: System) {
width: 800,
height: 600,
center: true,
title: i18n("computer"),
title: t("computer"),
content: "MyComputer",
//icon: myComputerLogoIcon,
icon: "computer",

2
frontend/src/system/window/Dialog.ts

@ -43,7 +43,7 @@ class Dialog {
function setProgress(value: number) {
process.value = value;
if (value >= 100) {
//dialogwin.close();
dialogwin.close();
}
}

3
libs/dir.go

@ -2,7 +2,6 @@ package libs
import (
"fmt"
"log"
"os"
"path/filepath"
"runtime"
@ -43,7 +42,7 @@ func InitOsDir() (string, error) {
func GetOsDir() (string, error) {
osDirInfo, _ := GetConfig("osInfo")
res := osDirInfo.Value
log.Printf("=====osInfo: %s", res)
//log.Printf("=====osInfo: %s", res)
// if osDirInfo.UserType == "member" {
// res = filepath.Join(res, osDirInfo.UserName)
// }

31
localchat/client.go

@ -9,32 +9,6 @@ import (
"time"
)
// func StartServiceDiscovery() {
// conn, err := net.ListenPacket("udp", broadcastAddr)
// if err != nil {
// fmt.Println(err)
// return
// }
// defer conn.Close()
// buffer := make([]byte, 1024)
// for {
// n, addr, err := conn.ReadFrom(buffer)
// if err != nil {
// fmt.Println(err)
// continue
// }
// fmt.Printf("Received message: %s from %s\n", buffer[:n], addr)
// var udpMsg UdpMessage
// err = json.Unmarshal(buffer[:n], &udpMsg)
// if err != nil {
// fmt.Printf("Error unmarshalling JSON: %v\n", err)
// continue
// }
// log.Printf("Get message: %+v", udpMsg)
// OnlineUsers[udpMsg.IP] = udpMsg
// }
// }
func DiscoverServers() {
broadcastTicker := time.NewTicker(broadcartTime)
done := make(chan struct{}) // New channel to signal when to stop
@ -80,11 +54,6 @@ func DiscoverServers() {
}
}
}()
// You might have some condition here to decide when to stop the ticker
// For example, a signal handling mechanism or a specific duration.
// After that condition is met, you would call:
// close(done)
}
// 获取自己的IP地址和主机名

30
localchat/file.go

@ -1,44 +1,20 @@
package localchat
import (
"fmt"
"log"
"godoos/libs"
"os"
"path/filepath"
"time"
)
func GetChatPath() (string, error) {
baseDir, err := getAppDir()
baseDir, err := libs.GetOsDir()
if err != nil {
return "", err
}
modelDir := filepath.Join(baseDir, "C", "Users", "Reciv", time.Now().Format("2006-01-02"))
if !pathExists(modelDir) {
if !libs.PathExists(modelDir) {
os.MkdirAll(modelDir, 0755)
}
return modelDir, nil
}
func getAppDir() (string, error) {
homeDir, err := os.UserHomeDir()
if err != nil {
return "", fmt.Errorf("failed to get user home directory: %w", err)
}
return filepath.Join(homeDir, ".godoos", "os"), nil
}
func pathExists(dir string) bool {
_, err := os.Stat(dir)
if err == nil {
//log.Println("文件夹存在")
return true
} else if os.IsNotExist(err) {
//log.Println("文件夹不存在")
return false
} else if os.IsExist(err) {
//log.Println("文件夹存在")
return true
} else {
log.Println("发生错误:", err)
return false
}
}

46
localchat/server.go

@ -36,49 +36,3 @@ func StartServiceDiscovery() {
OnlineUsers[udpMsg.IP] = udpMsg
}
}
/*
func StartServiceDiscovery(port int, clientPort int) {
addr := fmt.Sprintf(":%d", port)
serviceAddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
log.Fatalf("Failed to resolve UDP address: %v", err)
}
conn, err := net.ListenUDP("udp", serviceAddr)
if err != nil {
log.Fatalf("Failed to listen on UDP: %v", err)
}
defer conn.Close()
buffer := make([]byte, 1024)
hostname, err := os.Hostname()
if err != nil {
log.Fatalf("Failed to get hostname: %v", err)
}
for {
// 监听UDP广播请求
_, _, err := conn.ReadFromUDP(buffer)
if err != nil {
log.Printf("Error reading from UDP: %v", err)
continue
}
// 构建广播消息,包含IP和主机名
ip, _, _ := net.SplitHostPort(serviceAddr.String())
response := fmt.Sprintf("Chat Server is running at IP: %s, Hostname: %s", ip, hostname)
broadcastMessage(conn, response, clientPort)
}
}
func broadcastMessage(conn *net.UDPConn, message string, clientPort int) {
// 广播给所有客户端
broadcastAddr := &net.UDPAddr{IP: net.ParseIP("255.255.255.255"), Port: clientPort}
_, err := conn.WriteToUDP([]byte(message), broadcastAddr)
if err != nil {
log.Printf("Failed to broadcast message: %v", err)
}
}
*/

3
localchat/upload.go

@ -3,6 +3,7 @@ package localchat
import (
"encoding/base64"
"fmt"
"godoos/libs"
"io"
"log"
"net/http"
@ -103,7 +104,7 @@ func SaveContentToFile(content, fileName string) (UploadInfo, error) {
if err != nil {
return UploadInfo{}, err
}
appDir, err := getAppDir()
appDir, err := libs.GetOsDir()
if err != nil {
return UploadInfo{}, err
}

63
localchat/windiscovery.go

@ -52,66 +52,3 @@ func StartServiceDiscovery() {
OnlineUsers[udpMsg.IP] = udpMsg
}
}
/*
// findMulticastInterface 查找适合多播的网络接口
func findMulticastInterface() (*net.Interface, error) {
ifaces, err := net.Interfaces()
if err != nil {
return nil, err
}
for _, iface := range ifaces {
if strings.HasPrefix(iface.Name, "eth") || strings.HasPrefix(iface.Name, "en") || strings.HasPrefix(iface.Name, "wlan") {
addrs, err := iface.Addrs()
if err != nil {
continue
}
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
}
if ip != nil && !ip.IsLoopback() {
return &iface, nil
}
}
}
}
return nil, fmt.Errorf("no suitable multicast interface found")
}
// setupWindowsMulticast 为Windows平台设置多播
func setupWindowsMulticast(conn net.PacketConn, iface *net.Interface, multicastIP net.IP) error {
// 获取文件描述符
if sock, err := conn.(*net.UDPConn).File(); err != nil {
return err
} else {
defer sock.Close()
fd := sock.Fd()
// 加入多播组
var mreq windows.RawSockaddrInet4
mreq.Family = windows.AF_INET
mreq.Port = 0
// 确保 multicastIP 是 IPv4 并转换为 [4]byte
ipv4 := multicastIP.To4()
if ipv4 == nil {
return errors.New("multicast IP is not an IPv4 address")
}
copy(mreq.Addr[:], ipv4)
if err := windows.SetsockoptIPv4MulticastInterface(fd, windows.IPMULTICAST_IF, &mreq); err != nil {
return err
}
// 绑定到特定接口(可选,根据需求调整)
ifaceIndex := uint32(iface.Index)
if err := windows.BindToDevice(fd, windows.StringToUTF16Ptr(fmt.Sprintf("%d", ifaceIndex))); err != nil {
return err
}
return nil
}
}*/

32
progress/start.go

@ -114,38 +114,6 @@ func ExecuteScript(name string) error {
// 设置并启动脚本执行命令
var cmd *exec.Cmd
//threadNum := runtime.NumCPU()
// switch name {
// // case "llmcpu":
// // params := []string{
// // strconv.Itoa(threadNum),
// // "127.0.0.1",
// // "56715",
// // }
// // cmd = exec.Command(scriptPath, params...)
// // case "llmgpu":
// // params := []string{
// // strconv.Itoa(threadNum),
// // "127.0.0.1",
// // "56719",
// // }
// // cmd = exec.Command(scriptPath, params...)
// case "ollama":
// os.Setenv("OLLAMA_HOST", "localhost:56715")
// //os.Setenv("OLLAMA_PORT", "56715")
// os.Setenv("OLLAMA_MODELS", OllamaModelsDir())
// os.Setenv("OLLAMA_ORIGINS", "wails://*")
// //log.Printf("OllamaModelsDir: %s", OllamaModelsDir())
// if runtime.GOOS == "windows" {
// os.Setenv("OLLAMA_RUNNERS_DIR", filepath.Join(exeDir, name, "ollama_runners"))
// }
// params := []string{
// "serve",
// }
// cmd = exec.Command(scriptPath, params...)
// default:
// cmd = exec.Command(scriptPath)
// }
cmd = exec.Command(scriptPath)
if runtime.GOOS == "windows" {
// 在Windows上,通过设置CreationFlags来隐藏窗口

Loading…
Cancel
Save