mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-28 01:53:53 +08:00
update: 音色克隆多语言配置
This commit is contained in:
@@ -1205,6 +1205,8 @@ export default {
|
|||||||
'voiceClone.operationClosed': 'Popup geschlossen',
|
'voiceClone.operationClosed': 'Popup geschlossen',
|
||||||
'voiceClone.cloneSuccess': 'Klonen erfolgreich',
|
'voiceClone.cloneSuccess': 'Klonen erfolgreich',
|
||||||
'voiceClone.cloneFailed': 'Klonen fehlgeschlagen',
|
'voiceClone.cloneFailed': 'Klonen fehlgeschlagen',
|
||||||
|
'voiceClone.cloneErrorTip': 'Klonen fehlgeschlagen, bitte bewegen Sie die Maus über die Fehlermeldung für Details',
|
||||||
|
'voiceClone.apiError': 'API-Aufruf Fehler',
|
||||||
'voiceClone.confirmClone': 'Sind Sie sicher, dass Sie diese Stimme klonen möchten?',
|
'voiceClone.confirmClone': 'Sind Sie sicher, dass Sie diese Stimme klonen möchten?',
|
||||||
'voiceClone.onlySuccessCanClone': 'Nur erfolgreich trainierte Stimmen können geklont werden',
|
'voiceClone.onlySuccessCanClone': 'Nur erfolgreich trainierte Stimmen können geklont werden',
|
||||||
'common.insufficient': 'Unzureichend',
|
'common.insufficient': 'Unzureichend',
|
||||||
@@ -1222,6 +1224,7 @@ export default {
|
|||||||
'voiceClone.training': 'Training',
|
'voiceClone.training': 'Training',
|
||||||
'voiceClone.trainSuccess': 'Training erfolgreich',
|
'voiceClone.trainSuccess': 'Training erfolgreich',
|
||||||
'voiceClone.trainFailed': 'Training fehlgeschlagen',
|
'voiceClone.trainFailed': 'Training fehlgeschlagen',
|
||||||
|
'voiceClone.trainFailedWithError': 'Training fehlgeschlagen: {error}',
|
||||||
'voiceClone.itemsPerPage': '{items} Einträge/Seite',
|
'voiceClone.itemsPerPage': '{items} Einträge/Seite',
|
||||||
'voiceClone.firstPage': 'Erste Seite',
|
'voiceClone.firstPage': 'Erste Seite',
|
||||||
'voiceClone.prevPage': 'Vorherige Seite',
|
'voiceClone.prevPage': 'Vorherige Seite',
|
||||||
|
|||||||
@@ -1205,6 +1205,8 @@ export default {
|
|||||||
'voiceClone.operationClosed': 'Popup closed',
|
'voiceClone.operationClosed': 'Popup closed',
|
||||||
'voiceClone.cloneSuccess': 'Clone successful',
|
'voiceClone.cloneSuccess': 'Clone successful',
|
||||||
'voiceClone.cloneFailed': 'Clone failed',
|
'voiceClone.cloneFailed': 'Clone failed',
|
||||||
|
'voiceClone.cloneErrorTip': 'Clone failed, please hover over the error tip to view error details',
|
||||||
|
'voiceClone.apiError': 'API call error',
|
||||||
'voiceClone.confirmClone': 'Are you sure you want to clone this voice?',
|
'voiceClone.confirmClone': 'Are you sure you want to clone this voice?',
|
||||||
'voiceClone.onlySuccessCanClone': 'Only successfully trained voices can be cloned',
|
'voiceClone.onlySuccessCanClone': 'Only successfully trained voices can be cloned',
|
||||||
'common.insufficient': 'Insufficient',
|
'common.insufficient': 'Insufficient',
|
||||||
@@ -1222,6 +1224,7 @@ export default {
|
|||||||
'voiceClone.training': 'Training',
|
'voiceClone.training': 'Training',
|
||||||
'voiceClone.trainSuccess': 'Training successful',
|
'voiceClone.trainSuccess': 'Training successful',
|
||||||
'voiceClone.trainFailed': 'Training failed',
|
'voiceClone.trainFailed': 'Training failed',
|
||||||
|
'voiceClone.trainFailedWithError': 'Training failed: {error}',
|
||||||
'voiceClone.itemsPerPage': '{items} items/page',
|
'voiceClone.itemsPerPage': '{items} items/page',
|
||||||
'voiceClone.firstPage': 'First Page',
|
'voiceClone.firstPage': 'First Page',
|
||||||
'voiceClone.prevPage': 'Previous Page',
|
'voiceClone.prevPage': 'Previous Page',
|
||||||
|
|||||||
@@ -1203,8 +1203,10 @@ export default {
|
|||||||
'voiceClone.selectFirst': 'Por favor, selecione recursos de voz para excluir primeiro',
|
'voiceClone.selectFirst': 'Por favor, selecione recursos de voz para excluir primeiro',
|
||||||
'voiceClone.operationCancelled': 'Cancelar',
|
'voiceClone.operationCancelled': 'Cancelar',
|
||||||
'voiceClone.operationClosed': 'Popup fechado',
|
'voiceClone.operationClosed': 'Popup fechado',
|
||||||
'voiceClone.cloneSuccess': 'Clonado com sucesso',
|
'voiceClone.cloneSuccess': 'Clonagem bem-sucedida',
|
||||||
'voiceClone.cloneFailed': 'Falha ao clonar',
|
'voiceClone.cloneFailed': 'Falha ao clonar',
|
||||||
|
'voiceClone.cloneErrorTip': 'Falha na clonagem, passe o mouse sobre a dica de erro para ver os detalhes',
|
||||||
|
'voiceClone.apiError': 'Erro na chamada da API',
|
||||||
'voiceClone.confirmClone': 'Tem certeza de que deseja clonar esta voz?',
|
'voiceClone.confirmClone': 'Tem certeza de que deseja clonar esta voz?',
|
||||||
'voiceClone.onlySuccessCanClone': 'Apenas vozes treinadas com sucesso podem ser clonadas',
|
'voiceClone.onlySuccessCanClone': 'Apenas vozes treinadas com sucesso podem ser clonadas',
|
||||||
'common.insufficient': 'Insuficiente',
|
'common.insufficient': 'Insuficiente',
|
||||||
@@ -1222,6 +1224,7 @@ export default {
|
|||||||
'voiceClone.training': 'Treinando',
|
'voiceClone.training': 'Treinando',
|
||||||
'voiceClone.trainSuccess': 'Treinamento bem-sucedido',
|
'voiceClone.trainSuccess': 'Treinamento bem-sucedido',
|
||||||
'voiceClone.trainFailed': 'Treinamento falhou',
|
'voiceClone.trainFailed': 'Treinamento falhou',
|
||||||
|
'voiceClone.trainFailedWithError': 'Treinamento falhou: {error}',
|
||||||
'voiceClone.itemsPerPage': '{items} itens/página',
|
'voiceClone.itemsPerPage': '{items} itens/página',
|
||||||
'voiceClone.firstPage': 'Primeira Página',
|
'voiceClone.firstPage': 'Primeira Página',
|
||||||
'voiceClone.prevPage': 'Página Anterior',
|
'voiceClone.prevPage': 'Página Anterior',
|
||||||
|
|||||||
@@ -1205,6 +1205,8 @@ export default {
|
|||||||
'voiceClone.operationClosed': 'Đã đóng popup',
|
'voiceClone.operationClosed': 'Đã đóng popup',
|
||||||
'voiceClone.cloneSuccess': 'Nhân bản thành công',
|
'voiceClone.cloneSuccess': 'Nhân bản thành công',
|
||||||
'voiceClone.cloneFailed': 'Nhân bản thất bại',
|
'voiceClone.cloneFailed': 'Nhân bản thất bại',
|
||||||
|
'voiceClone.cloneErrorTip': 'Nhân bản thất bại, hãy di chuột qua thông báo lỗi để xem chi tiết',
|
||||||
|
'voiceClone.apiError': 'Lỗi gọi API',
|
||||||
'voiceClone.confirmClone': 'Bạn có chắc chắn muốn nhân bản giọng này?',
|
'voiceClone.confirmClone': 'Bạn có chắc chắn muốn nhân bản giọng này?',
|
||||||
'voiceClone.onlySuccessCanClone': 'Chỉ có thể nhân bản giọng đã huấn luyện thành công',
|
'voiceClone.onlySuccessCanClone': 'Chỉ có thể nhân bản giọng đã huấn luyện thành công',
|
||||||
'common.insufficient': 'Không đủ',
|
'common.insufficient': 'Không đủ',
|
||||||
@@ -1222,6 +1224,7 @@ export default {
|
|||||||
'voiceClone.training': 'Đang huấn luyện',
|
'voiceClone.training': 'Đang huấn luyện',
|
||||||
'voiceClone.trainSuccess': 'Huấn luyện thành công',
|
'voiceClone.trainSuccess': 'Huấn luyện thành công',
|
||||||
'voiceClone.trainFailed': 'Huấn luyện thất bại',
|
'voiceClone.trainFailed': 'Huấn luyện thất bại',
|
||||||
|
'voiceClone.trainFailedWithError': 'Huấn luyện thất bại: {error}',
|
||||||
'voiceClone.itemsPerPage': '{items} mục/trang',
|
'voiceClone.itemsPerPage': '{items} mục/trang',
|
||||||
'voiceClone.firstPage': 'Trang đầu',
|
'voiceClone.firstPage': 'Trang đầu',
|
||||||
'voiceClone.prevPage': 'Trang trước',
|
'voiceClone.prevPage': 'Trang trước',
|
||||||
|
|||||||
@@ -1205,6 +1205,8 @@ export default {
|
|||||||
'voiceClone.action': '操作',
|
'voiceClone.action': '操作',
|
||||||
'voiceClone.cloneSuccess': '复刻成功',
|
'voiceClone.cloneSuccess': '复刻成功',
|
||||||
'voiceClone.cloneFailed': '复刻失败',
|
'voiceClone.cloneFailed': '复刻失败',
|
||||||
|
'voiceClone.cloneErrorTip': '克隆失败,请将鼠标悬停在错误提示上,查看错误详情',
|
||||||
|
'voiceClone.apiError': '调用API时出错',
|
||||||
'voiceClone.confirmClone': '确定要复刻此音色吗?',
|
'voiceClone.confirmClone': '确定要复刻此音色吗?',
|
||||||
'voiceClone.onlySuccessCanClone': '只有训练成功的音色才能复刻',
|
'voiceClone.onlySuccessCanClone': '只有训练成功的音色才能复刻',
|
||||||
'common.insufficient': '不足',
|
'common.insufficient': '不足',
|
||||||
@@ -1222,6 +1224,7 @@ export default {
|
|||||||
'voiceClone.training': '训练中',
|
'voiceClone.training': '训练中',
|
||||||
'voiceClone.trainSuccess': '训练成功',
|
'voiceClone.trainSuccess': '训练成功',
|
||||||
'voiceClone.trainFailed': '训练失败',
|
'voiceClone.trainFailed': '训练失败',
|
||||||
|
'voiceClone.trainFailedWithError': '训练失败:{error}',
|
||||||
'voiceClone.itemsPerPage': '{items}条/页',
|
'voiceClone.itemsPerPage': '{items}条/页',
|
||||||
'voiceClone.firstPage': '首页',
|
'voiceClone.firstPage': '首页',
|
||||||
'voiceClone.prevPage': '上一页',
|
'voiceClone.prevPage': '上一页',
|
||||||
|
|||||||
@@ -1205,6 +1205,8 @@ export default {
|
|||||||
'voiceClone.operationClosed': '已關閉彈窗',
|
'voiceClone.operationClosed': '已關閉彈窗',
|
||||||
'voiceClone.cloneSuccess': '複刻成功',
|
'voiceClone.cloneSuccess': '複刻成功',
|
||||||
'voiceClone.cloneFailed': '複刻失敗',
|
'voiceClone.cloneFailed': '複刻失敗',
|
||||||
|
'voiceClone.cloneErrorTip': '複刻失敗,請將鼠標懸停在錯誤提示上,查看錯誤詳情',
|
||||||
|
'voiceClone.apiError': '調用API時出錯',
|
||||||
'voiceClone.confirmClone': '確定要複刻此音色嗎?',
|
'voiceClone.confirmClone': '確定要複刻此音色嗎?',
|
||||||
'voiceClone.onlySuccessCanClone': '只有訓練成功的音色才能複刻',
|
'voiceClone.onlySuccessCanClone': '只有訓練成功的音色才能複刻',
|
||||||
'common.insufficient': '不足',
|
'common.insufficient': '不足',
|
||||||
@@ -1222,6 +1224,7 @@ export default {
|
|||||||
'voiceClone.training': '訓練中',
|
'voiceClone.training': '訓練中',
|
||||||
'voiceClone.trainSuccess': '訓練成功',
|
'voiceClone.trainSuccess': '訓練成功',
|
||||||
'voiceClone.trainFailed': '訓練失敗',
|
'voiceClone.trainFailed': '訓練失敗',
|
||||||
|
'voiceClone.trainFailedWithError': '訓練失敗:{error}',
|
||||||
'voiceClone.itemsPerPage': '{items}條/頁',
|
'voiceClone.itemsPerPage': '{items}條/頁',
|
||||||
'voiceClone.firstPage': '首頁',
|
'voiceClone.firstPage': '首頁',
|
||||||
'voiceClone.prevPage': '上一頁',
|
'voiceClone.prevPage': '上一頁',
|
||||||
|
|||||||
@@ -34,20 +34,14 @@
|
|||||||
<span class="info-label">{{ $t('voiceClone.languages') }}</span>
|
<span class="info-label">{{ $t('voiceClone.languages') }}</span>
|
||||||
<span class="info-value">{{ item.languages || '-' }}</span>
|
<span class="info-value">{{ item.languages || '-' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="info-row">
|
|
||||||
<span class="info-label">模型名称</span>
|
|
||||||
<span class="info-value" :title="item.modelName">{{ item.modelName || '-' }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-row">
|
|
||||||
<span class="info-label">{{ $t('voiceClone.createdAt') }}</span>
|
|
||||||
<span class="info-value">{{ formatDate(item.createDate) }}</span>
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-right" :class="{ 'info-right--centered': !item.hasVoice }">
|
<div class="info-right" :class="{ 'info-right--centered': !item.hasVoice }">
|
||||||
<div class="status-button" :class="getStatusButtonClass(item)">
|
<el-tooltip :content="getTooltipContent(item)" placement="top" effect="light">
|
||||||
<span>{{ getTrainStatusText(item) }}</span>
|
<div class="status-button" :class="getStatusButtonClass(item)">
|
||||||
</div>
|
<span>{{ getTrainStatusText(item) }}</span>
|
||||||
|
</div>
|
||||||
|
</el-tooltip>
|
||||||
<div v-if="item.hasVoice" class="voice-wave" :class="{ 'is-playing': playingRowId === item.id }">
|
<div v-if="item.hasVoice" class="voice-wave" :class="{ 'is-playing': playingRowId === item.id }">
|
||||||
<span class="wave-bar"></span>
|
<span class="wave-bar"></span>
|
||||||
<span class="wave-bar"></span>
|
<span class="wave-bar"></span>
|
||||||
@@ -80,7 +74,7 @@
|
|||||||
<el-button size="mini" type="text"
|
<el-button size="mini" type="text"
|
||||||
:icon="item.isEdit ? 'el-icon-check' : 'el-icon-edit'"
|
:icon="item.isEdit ? 'el-icon-check' : 'el-icon-edit'"
|
||||||
@click="handleEditButtonClick(item)">
|
@click="handleEditButtonClick(item)">
|
||||||
{{ item.isEdit ? '保存' : '编辑' }}
|
{{ item.isEdit ? $t('button.save') : $t('common.edit') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -149,18 +143,18 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
getTooltipContent(row) {
|
getTooltipContent(row) {
|
||||||
if (!row.hasVoice) {
|
if (!row.hasVoice) {
|
||||||
return '待上传';
|
return this.$t('voiceClone.waitingUpload');
|
||||||
}
|
}
|
||||||
switch (row.trainStatus) {
|
switch (row.trainStatus) {
|
||||||
case 0:
|
case 0:
|
||||||
return '待复刻';
|
return this.$t('voiceClone.waitingTraining');
|
||||||
case 2:
|
case 2:
|
||||||
return '训练成功';
|
return this.$t('voiceClone.trainSuccess');
|
||||||
case 3:
|
case 3:
|
||||||
if (row.trainError) {
|
if (row.trainError) {
|
||||||
return `训练失败:${row.trainError}`;
|
return this.$t('voiceClone.trainFailedWithError', { error: row.trainError });
|
||||||
}
|
}
|
||||||
return '训练失败';
|
return this.$t('voiceClone.trainFailed');
|
||||||
default:
|
default:
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -260,13 +254,13 @@ export default {
|
|||||||
}
|
}
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
console.error('API调用失败:', error);
|
console.error('API调用失败:', error);
|
||||||
this.$message.error('克隆失败,请将鼠标悬停在错误提示上,查看错误详情');
|
this.$message.error(this.$t('voiceClone.cloneErrorTip'));
|
||||||
this.fetchVoiceCloneList();
|
this.fetchVoiceCloneList();
|
||||||
this.$set(row, '_cloning', false);
|
this.$set(row, '_cloning', false);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('调用API时出错:', error);
|
console.error('调用API时出错:', error);
|
||||||
this.$message.error('调用API时出错');
|
this.$message.error(this.$t('voiceClone.apiError'));
|
||||||
this.fetchVoiceCloneList();
|
this.fetchVoiceCloneList();
|
||||||
this.$set(row, '_cloning', false);
|
this.$set(row, '_cloning', false);
|
||||||
}
|
}
|
||||||
@@ -377,7 +371,7 @@ export default {
|
|||||||
position: relative;
|
position: relative;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background: linear-gradient(to bottom right, #dce8ff, #e4eeff, #e6cbfd) center;
|
background: #eff4ff;
|
||||||
-webkit-background-size: cover;
|
-webkit-background-size: cover;
|
||||||
-o-background-size: cover;
|
-o-background-size: cover;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -495,7 +489,7 @@ export default {
|
|||||||
gap: 14px;
|
gap: 14px;
|
||||||
padding: 16px 16px 8px;
|
padding: 16px 16px 8px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1px solid #ebeef5;
|
box-shadow: 0 0 10px 0 #e8ecf5;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
transition: box-shadow 0.2s, border-color 0.2s;
|
transition: box-shadow 0.2s, border-color 0.2s;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user