Skip to content

Commit b834478

Browse files
authored
Merge pull request Project-HAMi#68 from Nimbus318/feat/i18n
feat: add i18n support
2 parents 358165f + f8da029 commit b834478

72 files changed

Lines changed: 17130 additions & 12819 deletions

Some content is hidden

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

.dockerignore

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Dependencies
2+
node_modules
3+
packages/*/node_modules
4+
.pnpm-store
5+
6+
# Build outputs
7+
dist
8+
packages/*/dist
9+
coverage
10+
.nyc_output
11+
12+
# Git
13+
.git
14+
.gitignore
15+
.gitattributes
16+
17+
# CI/CD
18+
.github
19+
.gitlab-ci.yml
20+
21+
# Documentation
22+
docs
23+
*.md
24+
!README.md
25+
26+
# Development files
27+
.vscode
28+
.idea
29+
*.swp
30+
*.swo
31+
*~
32+
33+
# Logs
34+
logs
35+
*.log
36+
npm-debug.log*
37+
pnpm-debug.log*
38+
yarn-debug.log*
39+
yarn-error.log*
40+
41+
# OS files
42+
.DS_Store
43+
Thumbs.db
44+
45+
# Test files
46+
test
47+
*.spec.ts
48+
*.test.ts
49+
jest.config.*
50+
.eslintrc.*
51+
.prettierrc.*
52+
53+
# Server (backend is built separately)
54+
server
55+
56+
# Charts
57+
charts
58+
59+
# Scripts (not needed in production)
60+
scripts
61+
62+
# Temporary files
63+
tmp
64+
*.tmp
65+
*.temp
66+
67+
# Environment files (should be provided at runtime)
68+
.env
69+
.env.*
70+
!.env.example
71+

.eslintrc.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
module.exports = {
22
root: true,
33
parserOptions: {
4-
parser: 'babel-eslint',
4+
// Use TypeScript-aware parser; replaces deprecated babel-eslint.
5+
parser: '@typescript-eslint/parser',
56
sourceType: 'module'
67
},
78
env: {
89
browser: true,
910
node: true,
1011
es6: true
1112
},
13+
plugins: ['@typescript-eslint'],
1214
extends: ['plugin:vue/recommended', 'eslint:recommended'],
1315

1416
// add your custom rules here
1517
// it is base on https://github.com/vuejs/eslint-config-vue
1618
rules: {
1719
'vue/max-attributes-per-line': [2, {
1820
'singleline': 10,
19-
'multiline': {
20-
'max': 1,
21-
'allowFirstLine': false
22-
}
21+
// eslint-plugin-vue >=8 expects multiline to be a number or an object with only `max`
22+
'multiline': 1
2323
}],
2424
'vue/singleline-html-element-content-newline': 'off',
2525
'vue/multiline-html-element-content-newline': 'off',
@@ -148,7 +148,9 @@ module.exports = {
148148
}],
149149
'no-useless-call': 2,
150150
'no-useless-computed-key': 2,
151-
'no-useless-constructor': 2,
151+
// Use TS-aware version to allow parameter properties
152+
'no-useless-constructor': 'off',
153+
'@typescript-eslint/no-useless-constructor': 2,
152154
'no-useless-escape': 0,
153155
'no-whitespace-before-property': 2,
154156
'no-with': 2,
@@ -194,5 +196,11 @@ module.exports = {
194196
objectsInObjects: false
195197
}],
196198
'array-bracket-spacing': [2, 'never']
197-
}
199+
},
200+
overrides: [
201+
{
202+
files: ['**/*.spec.ts', 'test/**/*.ts'],
203+
env: { jest: true }
204+
}
205+
]
198206
}

Dockerfile

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,51 @@ FROM --platform=$BUILDPLATFORM node:21.6.2 AS builder
22

33
WORKDIR /src
44

5-
# Cache dependencies
6-
COPY package.json yarn.lock ./
5+
# Enable corepack to use pnpm version from package.json packageManager field
6+
RUN corepack enable
7+
8+
# Copy dependency files for better layer caching
9+
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
710
COPY packages/web/package.json packages/web/
8-
RUN yarn install --frozen-lockfile
911

12+
# Install dependencies
13+
RUN pnpm install --frozen-lockfile
14+
15+
# Copy source code
1016
COPY . .
1117

12-
# Build
18+
# Build application
1319
RUN make build-bff build-web
1420

21+
# Remove devDependencies to reduce image size (only keep production dependencies)
22+
RUN CI=true pnpm prune --prod
23+
24+
# Clean pnpm store cache to reduce image size
25+
RUN pnpm store prune
26+
1527
FROM node:21.6.2-slim
1628

17-
COPY --from=builder /src/dist/ /apps/dist/
18-
COPY --from=builder /src/node_modules/ /apps/node_modules/
19-
COPY --from=builder /src/public/ /apps/public/
29+
# Set production environment
30+
ENV NODE_ENV=production
31+
32+
# Create app directory and non-root user for security
33+
WORKDIR /apps
34+
RUN groupadd -r appuser && useradd -r -g appuser appuser
35+
36+
# Copy built artifacts from builder stage
37+
COPY --from=builder --chown=appuser:appuser /src/dist/ ./dist/
38+
COPY --from=builder --chown=appuser:appuser /src/node_modules/ ./node_modules/
39+
COPY --from=builder --chown=appuser:appuser /src/public/ ./public/
40+
41+
# Switch to non-root user
42+
USER appuser
43+
44+
# Expose port
45+
EXPOSE 3000
46+
47+
# Health check using the application's health_check endpoint
48+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
49+
CMD node -e "require('http').get('http://localhost:3000/health_check', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})" || exit 1
50+
51+
# Start application
52+
CMD ["node", "dist/main"]

Makefile

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,34 +10,34 @@ DISABLED_PROJECTS?=""
1010

1111
.PHONY: install-modules
1212
install-modules:
13-
yarn install
13+
pnpm install
1414

1515
.PHONY: build-all
1616
build-all: install-modules build-bff build-web
1717

1818
.PHONY: build-bff
1919
build-bff:
20-
yarn run build
20+
pnpm run build
2121

2222
.PHONY: build-web
2323
build-web:
24-
yarn workspace hami-webui-web run build
24+
pnpm --filter hami-webui-web run build
2525

2626
.PHONY: start-dev
2727
start-dev: install-modules start-bff start-web
2828

2929

3030
.PHONY: start-bff
3131
start-bff:
32-
yarn run start:dev &
32+
pnpm run start:dev &
3333

3434
.PHONY: start-web
3535
start-web:
36-
yarn workspace hami-webui-web run start:dev
36+
pnpm --filter hami-webui-web run start:dev
3737

3838
.PHONY: start-prod
3939
start-prod:
40-
yarn run start:prod
40+
pnpm run start:prod
4141

4242
.PHONY: build-image
4343
build-image:
@@ -48,4 +48,4 @@ push-image:
4848
docker push ${DOCKER_IMAGE}:${VERSION}
4949

5050
.PHONY: release
51-
release: build-image push-image
51+
release: build-image push-image

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"author": "",
66
"private": true,
77
"license": "UNLICENSED",
8+
"packageManager": "pnpm@10.25.0",
89
"workspaces": [
910
"packages/*"
1011
],
@@ -15,7 +16,7 @@
1516
"start:dev": "export NODE_ENV=development && nest start --watch",
1617
"start:debug": "export NODE_ENV=development && nest start --debug --watch",
1718
"start:prod": "node dist/main",
18-
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
19+
"lint": "NODE_OPTIONS=\"--require ./scripts/structured-clone-polyfill.js\" eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
1920
"test": "jest",
2021
"test:watch": "jest --watch",
2122
"test:cov": "jest --coverage",
@@ -51,9 +52,9 @@
5152
"@types/jest": "^29.5.2",
5253
"@types/node": "^20.3.1",
5354
"@types/supertest": "^2.0.12",
54-
"@typescript-eslint/eslint-plugin": "^6.0.0",
55-
"@typescript-eslint/parser": "^6.0.0",
56-
"eslint": "^8.42.0",
55+
"@typescript-eslint/eslint-plugin": "^8.49.0",
56+
"@typescript-eslint/parser": "^8.49.0",
57+
"eslint": "^8.57.0",
5758
"eslint-config-prettier": "^9.0.0",
5859
"eslint-plugin-prettier": "^5.0.0",
5960
"jest": "^29.5.0",

packages/web/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22

33
## Project setup
44
```
5-
yarn install
5+
pnpm install
66
```
77

88
### Compiles and hot-reloads for development
99
```
10-
yarn serve
10+
pnpm run start:dev
1111
```
1212

1313
### Compiles and minifies for production
1414
```
15-
yarn build
15+
pnpm run build
1616
```
1717

1818
### Lints and fixes files
1919
```
20-
yarn lint
20+
pnpm run lint
2121
```
2222

2323
### Customize configuration

packages/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"vue": "^3.2.13",
4444
"vue-clipboard3": "2.0.0",
4545
"vue-count-to": "1.0.13",
46+
"vue-i18n": "9",
4647
"vue-native-websocket-vue3": "^3.1.7",
4748
"vue-router": "^4.0.3",
4849
"vuedraggable": "^4.1.0",

packages/web/projects/vgpu/components/TabTop.vue

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
<script setup>
2626
import BlockBox from '@/components/BlockBox.vue';
27-
import { onMounted, ref } from 'vue';
27+
import { onMounted, ref, watch } from 'vue';
2828
import EchartsPlus from '@/components/Echarts-plus.vue';
2929
import cardApi from '~/vgpu/api/card';
3030
import { cloneDeep } from 'lodash';
@@ -103,19 +103,33 @@ const getTopOptions = () => {
103103
};
104104
};
105105
106-
onMounted(async () => {
107-
tabActive.value = currentConfig.value[0].key;
108-
currentConfig.value.forEach((v, i) => {
106+
const fetchData = (configList) => {
107+
if (!configList?.length) return;
108+
tabActive.value = configList[0].key;
109+
configList.forEach((v, i) => {
109110
cardApi
110111
.getInstantVector({
111112
query: v.query,
112113
})
113114
.then((res) => {
114-
currentConfig.value[i].data = res.data.map((item) => ({
115+
configList[i].data = res.data.map((item) => ({
115116
name: item.metric[v.nameKey],
116117
value: item.value,
117118
}));
118119
});
119120
});
121+
};
122+
123+
onMounted(() => {
124+
fetchData(currentConfig.value);
120125
});
126+
127+
watch(
128+
() => props.config,
129+
(val) => {
130+
currentConfig.value = cloneDeep(val);
131+
fetchData(currentConfig.value);
132+
},
133+
{ deep: true },
134+
);
121135
</script>

packages/web/projects/vgpu/components/gauge.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@
55
class="gauge-box-echarts"
66
/>
77
<div class="gauge-info" v-if="!hideInfo">
8-
<span>{{ title.includes('使用') ? '使用' : '分配' }}</span>
9-
<span v-if="!title.includes('算力')">({{ unit }})</span> :
8+
<span>{{ title.includes('使用') || title.includes('Usage') ? $t('dashboard.usage') : $t('dashboard.allocation') }}</span>
9+
<span v-if="!title.includes('算力') && !title.includes('Compute')">({{ unit }})</span> :
1010
<b>{{ used.toFixed(1) }}/{{ total.toFixed() }}</b>
1111
</div>
1212
</div>
1313
</template>
1414
<script setup>
1515
import EchartsPlus from '@/components/Echarts-plus.vue';
1616
import getOptions from './config';
17+
import { useI18n } from 'vue-i18n';
18+
19+
const { t } = useI18n();
1720
1821
1922
const props = defineProps([

0 commit comments

Comments
 (0)