Spaces:
Running
Running
Upload 6 files
Browse files- control.js +78 -3
- index.html +97 -78
- prompt.js +68 -5
- translation.js +53 -9
control.js
CHANGED
@@ -15,10 +15,21 @@ document.addEventListener('keydown', function (event) {
|
|
15 |
}
|
16 |
});
|
17 |
|
18 |
-
//
|
19 |
document.getElementById('sidebarToggle').addEventListener('click', function () {
|
20 |
-
document.getElementById('sidebar')
|
21 |
-
document.getElementById('content')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
});
|
23 |
|
24 |
function resizeQueryTextarea() {
|
@@ -29,6 +40,70 @@ function resizeQueryTextarea() {
|
|
29 |
|
30 |
document.addEventListener('DOMContentLoaded', function () {
|
31 |
resizeQueryTextarea();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
});
|
33 |
|
34 |
window.addEventListener('resize', resizeQueryTextarea);
|
|
|
15 |
}
|
16 |
});
|
17 |
|
18 |
+
// サイドバーの切り替え機能を修正
|
19 |
document.getElementById('sidebarToggle').addEventListener('click', function () {
|
20 |
+
const sidebarContainer = document.getElementById('sidebar-container');
|
21 |
+
const content = document.getElementById('content');
|
22 |
+
const isActive = sidebarContainer.classList.toggle('active');
|
23 |
+
|
24 |
+
if (isActive) {
|
25 |
+
// サイドバーを開く
|
26 |
+
sidebarContainer.style.width = '250px';
|
27 |
+
content.style.marginLeft = '250px';
|
28 |
+
} else {
|
29 |
+
// サイドバーを閉じる
|
30 |
+
sidebarContainer.style.width = '0';
|
31 |
+
content.style.marginLeft = '0';
|
32 |
+
}
|
33 |
});
|
34 |
|
35 |
function resizeQueryTextarea() {
|
|
|
40 |
|
41 |
document.addEventListener('DOMContentLoaded', function () {
|
42 |
resizeQueryTextarea();
|
43 |
+
initSidebarResize(); // 新しい関数を呼び出し
|
44 |
+
});
|
45 |
+
|
46 |
+
window.addEventListener('resize', resizeQueryTextarea);
|
47 |
+
|
48 |
+
// サイドバーのリサイズ機能を修正
|
49 |
+
function initSidebarResize() {
|
50 |
+
const sidebarContainer = document.getElementById('sidebar-container');
|
51 |
+
const content = document.getElementById('content');
|
52 |
+
const resizer = document.getElementById('sidebar-resizer');
|
53 |
+
let isResizing = false;
|
54 |
+
|
55 |
+
resizer.addEventListener('mousedown', (e) => {
|
56 |
+
isResizing = true;
|
57 |
+
document.addEventListener('mousemove', resize);
|
58 |
+
document.addEventListener('mouseup', stopResize);
|
59 |
+
});
|
60 |
+
|
61 |
+
function resize(e) {
|
62 |
+
if (!isResizing) return;
|
63 |
+
const newWidth = e.clientX;
|
64 |
+
const minWidth = 250;
|
65 |
+
const maxWidth = 500;
|
66 |
+
const sidebarWidth = Math.min(Math.max(minWidth, newWidth), maxWidth);
|
67 |
+
|
68 |
+
sidebarContainer.style.width = `${sidebarWidth}px`;
|
69 |
+
content.style.marginLeft = `${sidebarWidth}px`;
|
70 |
+
sidebarContainer.classList.add('active'); // サイドバーを開いた状態にする
|
71 |
+
}
|
72 |
+
|
73 |
+
function stopResize() {
|
74 |
+
isResizing = false;
|
75 |
+
document.removeEventListener('mousemove', resize);
|
76 |
+
document.removeEventListener('mouseup', stopResize);
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
// localStorageをクリアする機能を追加
|
81 |
+
function initClearStorageButton() {
|
82 |
+
const clearStorageButton = document.getElementById('clearStorageButton');
|
83 |
+
clearStorageButton.addEventListener('click', () => {
|
84 |
+
const userInput = prompt('全てのデータを削除します。よろしければ「YES」と入力してください。');
|
85 |
+
if (userInput === 'YES') {
|
86 |
+
localStorage.clear();
|
87 |
+
alert('全てのデータが削除されました。ページを再読み込みします。');
|
88 |
+
location.reload();
|
89 |
+
} else {
|
90 |
+
alert('削除がキャンセルされました。');
|
91 |
+
}
|
92 |
+
});
|
93 |
+
}
|
94 |
+
|
95 |
+
// DOMContentLoadedイベントリスナーを更新
|
96 |
+
document.addEventListener('DOMContentLoaded', function () {
|
97 |
+
resizeQueryTextarea();
|
98 |
+
initSidebarResize();
|
99 |
+
initClearStorageButton();
|
100 |
+
// addDynamicStyles(); // この行を削除
|
101 |
+
|
102 |
+
// 初期状態でサイドバーを非表示にする処理も不要になるため、削除
|
103 |
+
// const sidebarContainer = document.getElementById('sidebar-container');
|
104 |
+
// const content = document.getElementById('content');
|
105 |
+
// sidebarContainer.classList.remove('active');
|
106 |
+
// content.classList.remove('sidebar-active');
|
107 |
});
|
108 |
|
109 |
window.addEventListener('resize', resizeQueryTextarea);
|
index.html
CHANGED
@@ -12,49 +12,45 @@
|
|
12 |
textarea.form-control {
|
13 |
min-height: 15vh;
|
14 |
}
|
15 |
-
|
|
|
16 |
position: fixed;
|
17 |
top: 0;
|
18 |
-
left:
|
19 |
-
width:
|
20 |
height: 100%;
|
21 |
-
|
22 |
-
transition: 0.3s;
|
23 |
z-index: 1000;
|
|
|
24 |
}
|
25 |
|
26 |
-
#sidebar
|
27 |
-
|
|
|
|
|
28 |
}
|
29 |
|
30 |
-
#
|
31 |
-
|
32 |
-
|
|
|
33 |
}
|
34 |
|
35 |
-
#content
|
36 |
-
margin-left:
|
|
|
37 |
}
|
38 |
|
39 |
#historyContainer {
|
40 |
-
max-height:
|
41 |
-
|
|
|
|
|
42 |
}
|
43 |
|
44 |
#historyContainer::-webkit-scrollbar {
|
45 |
-
width:
|
46 |
-
|
47 |
-
|
48 |
-
#historyContainer::-webkit-scrollbar-track {
|
49 |
-
background: #f1f1f1;
|
50 |
-
}
|
51 |
-
|
52 |
-
#historyContainer::-webkit-scrollbar-thumb {
|
53 |
-
background: #888;
|
54 |
-
}
|
55 |
-
|
56 |
-
#historyContainer::-webkit-scrollbar-thumb:hover {
|
57 |
-
background: #555;
|
58 |
}
|
59 |
|
60 |
.comic-animation {
|
@@ -81,6 +77,7 @@
|
|
81 |
width: 100%;
|
82 |
height: auto;
|
83 |
}
|
|
|
84 |
.form-group {
|
85 |
padding-left: 1rem;
|
86 |
padding-right: 1rem;
|
@@ -103,58 +100,78 @@
|
|
103 |
</head>
|
104 |
|
105 |
<body data-bs-theme="dark">
|
106 |
-
<div id="sidebar">
|
107 |
-
<div
|
108 |
-
<
|
109 |
-
|
110 |
-
<
|
111 |
-
<
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
<
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
<
|
122 |
-
|
123 |
-
<
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
<
|
135 |
-
|
136 |
-
<
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
|
|
142 |
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
|
|
|
|
150 |
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
</div>
|
157 |
</div>
|
|
|
158 |
</div>
|
159 |
|
160 |
<div id="content">
|
@@ -205,14 +222,16 @@
|
|
205 |
<textarea class="form-control" id="promptEn" placeholder="English Prompt"></textarea>
|
206 |
</div>
|
207 |
<div class="form-group mt-3">
|
208 |
-
<label for="promptMyLanguage" class="form-label" id="promptMyLanguageLabel">Your
|
|
|
209 |
<textarea class="form-control" id="promptMyLanguage" disabled></textarea>
|
210 |
</div>
|
211 |
<div class="form-group mt-3">
|
212 |
<label for="danbooruTags" class="form-label" id="danbooruTagsLabel">
|
213 |
danbooru tags
|
214 |
</label>
|
215 |
-
<input type="text" class="form-control" id="danbooruTags" placeholder="danbooru tags"
|
|
|
216 |
</div>
|
217 |
</div>
|
218 |
</div>
|
@@ -234,7 +253,7 @@
|
|
234 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/json5/2.2.3/index.min.js"
|
235 |
integrity="sha512-44jdhc+R2TFfzBflS3/dGNEABiNUxBkkrqwO7GWTvGsj3HkQNr3GESvI9PUvAxmqxSnTosR0Ij9y3+o+6J1hig=="
|
236 |
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
237 |
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/i18next/23.
|
238 |
integrity="sha512-8ANNUVMWPf6aWGXZqDhS4OXJWBCRxfjlW7lKfupuiG1FZah0ST6LiI2qnEb1L5mp05v/+0hn3s2FO4EwIbIgfA=="
|
239 |
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
240 |
<script
|
|
|
12 |
textarea.form-control {
|
13 |
min-height: 15vh;
|
14 |
}
|
15 |
+
|
16 |
+
#sidebar-container {
|
17 |
position: fixed;
|
18 |
top: 0;
|
19 |
+
left: 0;
|
20 |
+
width: 0; /* 初期幅を0に設定 */
|
21 |
height: 100%;
|
22 |
+
display: flex;
|
|
|
23 |
z-index: 1000;
|
24 |
+
transition: width 0.3s ease;
|
25 |
}
|
26 |
|
27 |
+
#sidebar {
|
28 |
+
flex-grow: 1;
|
29 |
+
overflow-y: auto;
|
30 |
+
background-color: #343a40;
|
31 |
}
|
32 |
|
33 |
+
#sidebar-resizer {
|
34 |
+
width: 10px;
|
35 |
+
cursor: ew-resize;
|
36 |
+
background-color: #2c3136;
|
37 |
}
|
38 |
|
39 |
+
#content {
|
40 |
+
margin-left: 0; /* 初期マージンを0に設定 */
|
41 |
+
transition: margin-left 0.3s ease;
|
42 |
}
|
43 |
|
44 |
#historyContainer {
|
45 |
+
max-height: none;
|
46 |
+
/* 最大高さの制限を解除 */
|
47 |
+
overflow-y: visible;
|
48 |
+
/* スクロールバーを削除 */
|
49 |
}
|
50 |
|
51 |
#historyContainer::-webkit-scrollbar {
|
52 |
+
width: 0;
|
53 |
+
/* スクロールバーを非表示に */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
}
|
55 |
|
56 |
.comic-animation {
|
|
|
77 |
width: 100%;
|
78 |
height: auto;
|
79 |
}
|
80 |
+
|
81 |
.form-group {
|
82 |
padding-left: 1rem;
|
83 |
padding-right: 1rem;
|
|
|
100 |
</head>
|
101 |
|
102 |
<body data-bs-theme="dark">
|
103 |
+
<div id="sidebar-container">
|
104 |
+
<div id="sidebar">
|
105 |
+
<div class="p-3">
|
106 |
+
<h3 id="settingsTitle" class="text-white">設定</h3>
|
107 |
+
<div class="form-group mb-3">
|
108 |
+
<label for="apiKey" class="form-label" id="apiKeyLabel">
|
109 |
+
<a href="https://aistudio.google.com/app/apikey?hl=ja" target="_blank">APIキー</a>
|
110 |
+
</label>
|
111 |
+
<input type="text" class="form-control" id="apiKey" placeholder="APIキーを入力してください">
|
112 |
+
</div>
|
113 |
+
<div class="form-group">
|
114 |
+
<label for="characterCount" class="form-label" id="characterCountLabel">文字数</label>
|
115 |
+
<input type="number" value="320" class="form-control" id="characterCount"
|
116 |
+
placeholder="生成するプロンプトの文字数を入力してください">
|
117 |
+
</div>
|
118 |
+
<div class="form-group">
|
119 |
+
<label for="languageSelect" class="form-label" id="languageSelectLabel">Language</label>
|
120 |
+
<select class="form-select" id="languageSelect">
|
121 |
+
<option value="ja">日本語</option>
|
122 |
+
<option value="en">English</option>
|
123 |
+
<option value="zh">中文</option>
|
124 |
+
<option value="ko">한국어</option>
|
125 |
+
<option value="fr">Français</option>
|
126 |
+
<option value="es">Español</option>
|
127 |
+
<option value="de">Deutsch</option>
|
128 |
+
<option value="it">Italiano</option>
|
129 |
+
</select>
|
130 |
+
</div>
|
131 |
+
<div class="form-group mb-3">
|
132 |
+
<label for="endpointSelect" class="form-label" id="endpointSelectLabel">エンドポイント</label>
|
133 |
+
<select class="form-select" id="endpointSelect">
|
134 |
+
<option value="gemini-1.5-pro-exp-0827">gemini-1.5-pro-exp-0827</option>
|
135 |
+
<option value="gemini-1.5-flash-exp-0827">gemini-1.5-flash-exp-0827</option>
|
136 |
+
<option value="gemini-1.5-pro-latest">gemini-1.5-pro-latest</option>
|
137 |
+
<option value="gemini-1.5-flash-latest">gemini-1.5-flash-latest</option>
|
138 |
+
</select>
|
139 |
+
</div>
|
140 |
|
141 |
+
<h3 id="replacementTitle" class="text-white mt-4">置換設定</h3>
|
142 |
+
<div id="replacementContainer">
|
143 |
+
<div id="replacementList">
|
144 |
+
<!-- 置換セットがここに動的に追加されます -->
|
145 |
+
</div>
|
146 |
+
<button id="addReplacementButton" class="btn btn-secondary mt-2">
|
147 |
+
<i class="fas fa-plus"></i> <span id="addReplacementButtonText">置換セット追加</span>
|
148 |
+
</button>
|
149 |
+
</div>
|
150 |
|
151 |
+
<h3 id="historyTitle" class="text-white mt-4">履歴</h3>
|
152 |
+
<div id="historyContainer">
|
153 |
+
<ul id="historyList" class="list-group small">
|
154 |
+
<!-- 履歴項目がここに動的に追加されます -->
|
155 |
+
</ul>
|
156 |
+
<p id="noHistoryMessage" class="text-white mt-2 d-none">履歴がありません。</p>
|
157 |
+
</div>
|
158 |
+
|
159 |
+
<!-- デバッグ用のモーダル表示ボタンを追加 -->
|
160 |
+
<div class="mt-4">
|
161 |
+
<button id="showLoadingModalButton" class="btn btn-secondary w-100">
|
162 |
+
Show Modal
|
163 |
+
</button>
|
164 |
+
</div>
|
165 |
+
|
166 |
+
<!-- 新しいボタンを追加 -->
|
167 |
+
<div class="mt-4">
|
168 |
+
<button id="clearStorageButton" class="btn btn-danger w-100">
|
169 |
+
全データを削除
|
170 |
+
</button>
|
171 |
+
</div>
|
172 |
</div>
|
173 |
</div>
|
174 |
+
<div id="sidebar-resizer"></div>
|
175 |
</div>
|
176 |
|
177 |
<div id="content">
|
|
|
222 |
<textarea class="form-control" id="promptEn" placeholder="English Prompt"></textarea>
|
223 |
</div>
|
224 |
<div class="form-group mt-3">
|
225 |
+
<label for="promptMyLanguage" class="form-label" id="promptMyLanguageLabel">Your
|
226 |
+
Language Translation</label>
|
227 |
<textarea class="form-control" id="promptMyLanguage" disabled></textarea>
|
228 |
</div>
|
229 |
<div class="form-group mt-3">
|
230 |
<label for="danbooruTags" class="form-label" id="danbooruTagsLabel">
|
231 |
danbooru tags
|
232 |
</label>
|
233 |
+
<input type="text" class="form-control" id="danbooruTags" placeholder="danbooru tags"
|
234 |
+
readonly>
|
235 |
</div>
|
236 |
</div>
|
237 |
</div>
|
|
|
253 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/json5/2.2.3/index.min.js"
|
254 |
integrity="sha512-44jdhc+R2TFfzBflS3/dGNEABiNUxBkkrqwO7GWTvGsj3HkQNr3GESvI9PUvAxmqxSnTosR0Ij9y3+o+6J1hig=="
|
255 |
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
256 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/i18next/23.15.1/i18next.min.js"
|
257 |
integrity="sha512-8ANNUVMWPf6aWGXZqDhS4OXJWBCRxfjlW7lKfupuiG1FZah0ST6LiI2qnEb1L5mp05v/+0hn3s2FO4EwIbIgfA=="
|
258 |
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
259 |
<script
|
prompt.js
CHANGED
@@ -112,17 +112,22 @@ function generatePrompt() {
|
|
112 |
[promptEn, promptMyLanguage] = [promptEn, promptMyLanguage].map(x => {
|
113 |
return Array.isArray(x) ? x.join("") : x;
|
114 |
});
|
115 |
-
|
116 |
-
|
117 |
-
document.getElementById('promptMyLanguage').value = promptMyLanguage
|
|
|
|
|
|
|
|
|
|
|
118 |
|
119 |
let danbooruTags = parsedData.results.find(x => x.language === 'danbooru');
|
120 |
if (danbooruTags.tags) {
|
121 |
-
danbooruTags = danbooruTags.tags.map(x => x.replace("_", " "));
|
122 |
document.getElementById('danbooruTags').value = danbooruTags.join(", ");
|
123 |
}
|
124 |
if (danbooruTags.text) {
|
125 |
-
danbooruTags = danbooruTags.text.map(x => x.replace("_", " "));
|
126 |
document.getElementById('danbooruTags').value = danbooruTags.join(", ");
|
127 |
}
|
128 |
|
@@ -161,3 +166,61 @@ function generatePrompt() {
|
|
161 |
});
|
162 |
};
|
163 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
[promptEn, promptMyLanguage] = [promptEn, promptMyLanguage].map(x => {
|
113 |
return Array.isArray(x) ? x.join("") : x;
|
114 |
});
|
115 |
+
|
116 |
+
promptMyLanguage = promptMyLanguage.replace(/\。 ?/g, '。\n\n');
|
117 |
+
document.getElementById('promptMyLanguage').value = promptMyLanguage;
|
118 |
+
|
119 |
+
promptEn = promptEn.replace(/\. ?/g, '.\n\n');
|
120 |
+
promptEn = promptEn.replace(/^ */g, '');
|
121 |
+
promptEn = applyReplacements(promptEn);
|
122 |
+
document.getElementById('promptEn').value = promptEn;
|
123 |
|
124 |
let danbooruTags = parsedData.results.find(x => x.language === 'danbooru');
|
125 |
if (danbooruTags.tags) {
|
126 |
+
danbooruTags = danbooruTags.tags.map(x => applyReplacements(x.replace("_", " ")));
|
127 |
document.getElementById('danbooruTags').value = danbooruTags.join(", ");
|
128 |
}
|
129 |
if (danbooruTags.text) {
|
130 |
+
danbooruTags = danbooruTags.text.map(x => applyReplacements(x.replace("_", " ")));
|
131 |
document.getElementById('danbooruTags').value = danbooruTags.join(", ");
|
132 |
}
|
133 |
|
|
|
166 |
});
|
167 |
};
|
168 |
|
169 |
+
function applyReplacements(text) {
|
170 |
+
const replacements = getReplacements();
|
171 |
+
for (const [search, replace] of replacements) {
|
172 |
+
text = text.replace(new RegExp(search, 'g'), replace);
|
173 |
+
}
|
174 |
+
return text;
|
175 |
+
}
|
176 |
+
|
177 |
+
function getReplacements() {
|
178 |
+
const replacementList = document.getElementById('replacementList');
|
179 |
+
const replacements = [];
|
180 |
+
for (const set of replacementList.children) {
|
181 |
+
const search = set.querySelector('.replacement-search').value;
|
182 |
+
const replace = set.querySelector('.replacement-replace').value;
|
183 |
+
if (search && replace) {
|
184 |
+
replacements.push([search, replace]);
|
185 |
+
}
|
186 |
+
}
|
187 |
+
return replacements;
|
188 |
+
}
|
189 |
+
|
190 |
+
// 置換セットの追加と削除の処理
|
191 |
+
document.getElementById('addReplacementButton').addEventListener('click', addReplacementSet);
|
192 |
+
|
193 |
+
function addReplacementSet() {
|
194 |
+
const replacementList = document.getElementById('replacementList');
|
195 |
+
const newSet = document.createElement('div');
|
196 |
+
newSet.className = 'replacement-set mb-2';
|
197 |
+
newSet.innerHTML = `
|
198 |
+
<input type="text" class="form-control form-control-sm replacement-search mb-1" placeholder="検索語">
|
199 |
+
<input type="text" class="form-control form-control-sm replacement-replace mb-1" placeholder="置換語">
|
200 |
+
<button class="btn btn-danger btn-sm remove-replacement">
|
201 |
+
<i class="fas fa-times"></i>
|
202 |
+
</button>
|
203 |
+
`;
|
204 |
+
replacementList.appendChild(newSet);
|
205 |
+
|
206 |
+
newSet.querySelector('.remove-replacement').addEventListener('click', function() {
|
207 |
+
replacementList.removeChild(newSet);
|
208 |
+
});
|
209 |
+
}
|
210 |
+
|
211 |
+
// ページ読み込み時に保存された置換セットを復元
|
212 |
+
window.addEventListener('load', function() {
|
213 |
+
const savedReplacements = JSON.parse(localStorage.getItem('replacements') || '[]');
|
214 |
+
for (const [search, replace] of savedReplacements) {
|
215 |
+
addReplacementSet();
|
216 |
+
const lastSet = document.getElementById('replacementList').lastElementChild;
|
217 |
+
lastSet.querySelector('.replacement-search').value = search;
|
218 |
+
lastSet.querySelector('.replacement-replace').value = replace;
|
219 |
+
}
|
220 |
+
});
|
221 |
+
|
222 |
+
// ページを離れる前に置換セットを保存
|
223 |
+
window.addEventListener('beforeunload', function() {
|
224 |
+
localStorage.setItem('replacements', JSON.stringify(getReplacements()));
|
225 |
+
});
|
226 |
+
|
translation.js
CHANGED
@@ -14,7 +14,11 @@ const translations = {
|
|
14 |
characterCountPlaceholder: "生成するプロンプトの文字数を入力してください",
|
15 |
endpointSelectLabel: "エンドポイント",
|
16 |
historyTitle: "履歴",
|
17 |
-
noHistoryMessage: "履歴がありません。"
|
|
|
|
|
|
|
|
|
18 |
},
|
19 |
en: {
|
20 |
inputQueryTitle: "Input Query",
|
@@ -31,7 +35,11 @@ const translations = {
|
|
31 |
characterCountPlaceholder: "Enter the number of characters for the generated prompt",
|
32 |
endpointSelectLabel: "Endpoint",
|
33 |
historyTitle: "History",
|
34 |
-
noHistoryMessage: "No history available."
|
|
|
|
|
|
|
|
|
35 |
},
|
36 |
zh: {
|
37 |
inputQueryTitle: "输入查询",
|
@@ -48,7 +56,11 @@ const translations = {
|
|
48 |
characterCountPlaceholder: "请输入生成提示的字符数",
|
49 |
endpointSelectLabel: "端点",
|
50 |
historyTitle: "历史记录",
|
51 |
-
noHistoryMessage: "没有可用的历史记录。"
|
|
|
|
|
|
|
|
|
52 |
},
|
53 |
ko: {
|
54 |
inputQueryTitle: "입력 쿼리",
|
@@ -65,7 +77,11 @@ const translations = {
|
|
65 |
characterCountPlaceholder: "생성할 프롬프트의 문자 수를 입력하세요",
|
66 |
endpointSelectLabel: "엔드포인트",
|
67 |
historyTitle: "기록",
|
68 |
-
noHistoryMessage: "사용 가능한 기록이 없습니다."
|
|
|
|
|
|
|
|
|
69 |
},
|
70 |
fr: {
|
71 |
inputQueryTitle: "Requête d'entrée",
|
@@ -82,7 +98,11 @@ const translations = {
|
|
82 |
characterCountPlaceholder: "Entrez le nombre de caractères pour le prompt généré",
|
83 |
endpointSelectLabel: "Point de terminaison",
|
84 |
historyTitle: "Historique",
|
85 |
-
noHistoryMessage: "Aucun historique disponible."
|
|
|
|
|
|
|
|
|
86 |
},
|
87 |
es: {
|
88 |
inputQueryTitle: "Consulta de entrada",
|
@@ -99,7 +119,11 @@ const translations = {
|
|
99 |
characterCountPlaceholder: "Ingrese el número de caracteres para el prompt generado",
|
100 |
endpointSelectLabel: "Punto final",
|
101 |
historyTitle: "Historial",
|
102 |
-
noHistoryMessage: "No hay historial disponible."
|
|
|
|
|
|
|
|
|
103 |
},
|
104 |
de: {
|
105 |
inputQueryTitle: "Eingabeabfrage",
|
@@ -116,7 +140,11 @@ const translations = {
|
|
116 |
characterCountPlaceholder: "Geben Sie die Anzahl der Zeichen für den generierten Prompt ein",
|
117 |
endpointSelectLabel: "Endpunkt",
|
118 |
historyTitle: "Verlauf",
|
119 |
-
noHistoryMessage: "Kein Verlauf verfügbar."
|
|
|
|
|
|
|
|
|
120 |
},
|
121 |
it: {
|
122 |
inputQueryTitle: "Query di input",
|
@@ -133,7 +161,11 @@ const translations = {
|
|
133 |
characterCountPlaceholder: "Inserisci il numero di caratteri per il prompt generato",
|
134 |
endpointSelectLabel: "Endpoint",
|
135 |
historyTitle: "Cronologia",
|
136 |
-
noHistoryMessage: "Nessuna cronologia disponibile."
|
|
|
|
|
|
|
|
|
137 |
}
|
138 |
}
|
139 |
const resources = {
|
@@ -196,8 +228,20 @@ function updateContent() {
|
|
196 |
|
197 |
// エンドポイントと履歴のテキストを更新
|
198 |
document.getElementById('endpointSelectLabel').textContent = i18next.t('endpointSelectLabel');
|
199 |
-
document.
|
200 |
document.getElementById('noHistoryMessage').textContent = i18next.t('noHistoryMessage');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
}
|
202 |
|
203 |
// 言語切り替え関数
|
|
|
14 |
characterCountPlaceholder: "生成するプロンプトの文字数を入力してください",
|
15 |
endpointSelectLabel: "エンドポイント",
|
16 |
historyTitle: "履歴",
|
17 |
+
noHistoryMessage: "履歴がありません。",
|
18 |
+
replacementTitle: "置換設定",
|
19 |
+
addReplacementButtonText: "置換セット追加",
|
20 |
+
replacementSearchPlaceholder: "検索語",
|
21 |
+
replacementReplacePlaceholder: "置換語"
|
22 |
},
|
23 |
en: {
|
24 |
inputQueryTitle: "Input Query",
|
|
|
35 |
characterCountPlaceholder: "Enter the number of characters for the generated prompt",
|
36 |
endpointSelectLabel: "Endpoint",
|
37 |
historyTitle: "History",
|
38 |
+
noHistoryMessage: "No history available.",
|
39 |
+
replacementTitle: "Replacement Settings",
|
40 |
+
addReplacementButtonText: "Add Replacement Set",
|
41 |
+
replacementSearchPlaceholder: "Search term",
|
42 |
+
replacementReplacePlaceholder: "Replace term"
|
43 |
},
|
44 |
zh: {
|
45 |
inputQueryTitle: "输入查询",
|
|
|
56 |
characterCountPlaceholder: "请输入生成提示的字符数",
|
57 |
endpointSelectLabel: "端点",
|
58 |
historyTitle: "历史记录",
|
59 |
+
noHistoryMessage: "没有可用的历史记录。",
|
60 |
+
replacementTitle: "替换设置",
|
61 |
+
addReplacementButtonText: "添加替换集",
|
62 |
+
replacementSearchPlaceholder: "搜索词",
|
63 |
+
replacementReplacePlaceholder: "替换词"
|
64 |
},
|
65 |
ko: {
|
66 |
inputQueryTitle: "입력 쿼리",
|
|
|
77 |
characterCountPlaceholder: "생성할 프롬프트의 문자 수를 입력하세요",
|
78 |
endpointSelectLabel: "엔드포인트",
|
79 |
historyTitle: "기록",
|
80 |
+
noHistoryMessage: "사용 가능한 기록이 없습니다.",
|
81 |
+
replacementTitle: "대체 설정",
|
82 |
+
addReplacementButtonText: "대체 세트 추가",
|
83 |
+
replacementSearchPlaceholder: "검색어",
|
84 |
+
replacementReplacePlaceholder: "대체어"
|
85 |
},
|
86 |
fr: {
|
87 |
inputQueryTitle: "Requête d'entrée",
|
|
|
98 |
characterCountPlaceholder: "Entrez le nombre de caractères pour le prompt généré",
|
99 |
endpointSelectLabel: "Point de terminaison",
|
100 |
historyTitle: "Historique",
|
101 |
+
noHistoryMessage: "Aucun historique disponible.",
|
102 |
+
replacementTitle: "Paramètres de remplacement",
|
103 |
+
addReplacementButtonText: "Ajouter un ensemble de remplacement",
|
104 |
+
replacementSearchPlaceholder: "Terme de recherche",
|
105 |
+
replacementReplacePlaceholder: "Terme de remplacement"
|
106 |
},
|
107 |
es: {
|
108 |
inputQueryTitle: "Consulta de entrada",
|
|
|
119 |
characterCountPlaceholder: "Ingrese el número de caracteres para el prompt generado",
|
120 |
endpointSelectLabel: "Punto final",
|
121 |
historyTitle: "Historial",
|
122 |
+
noHistoryMessage: "No hay historial disponible.",
|
123 |
+
replacementTitle: "Configuración de reemplazo",
|
124 |
+
addReplacementButtonText: "Agregar conjunto de reemplazo",
|
125 |
+
replacementSearchPlaceholder: "Término de búsqueda",
|
126 |
+
replacementReplacePlaceholder: "Término de reemplazo"
|
127 |
},
|
128 |
de: {
|
129 |
inputQueryTitle: "Eingabeabfrage",
|
|
|
140 |
characterCountPlaceholder: "Geben Sie die Anzahl der Zeichen für den generierten Prompt ein",
|
141 |
endpointSelectLabel: "Endpunkt",
|
142 |
historyTitle: "Verlauf",
|
143 |
+
noHistoryMessage: "Kein Verlauf verfügbar.",
|
144 |
+
replacementTitle: "Ersetzungseinstellungen",
|
145 |
+
addReplacementButtonText: "Ersetzungsset hinzufügen",
|
146 |
+
replacementSearchPlaceholder: "Suchbegriff",
|
147 |
+
replacementReplacePlaceholder: "Ersetzungsbegriff"
|
148 |
},
|
149 |
it: {
|
150 |
inputQueryTitle: "Query di input",
|
|
|
161 |
characterCountPlaceholder: "Inserisci il numero di caratteri per il prompt generato",
|
162 |
endpointSelectLabel: "Endpoint",
|
163 |
historyTitle: "Cronologia",
|
164 |
+
noHistoryMessage: "Nessuna cronologia disponibile.",
|
165 |
+
replacementTitle: "Impostazioni di sostituzione",
|
166 |
+
addReplacementButtonText: "Aggiungi set di sostituzione",
|
167 |
+
replacementSearchPlaceholder: "Termine di ricerca",
|
168 |
+
replacementReplacePlaceholder: "Termine di sostituzione"
|
169 |
}
|
170 |
}
|
171 |
const resources = {
|
|
|
228 |
|
229 |
// エンドポイントと履歴のテキストを更新
|
230 |
document.getElementById('endpointSelectLabel').textContent = i18next.t('endpointSelectLabel');
|
231 |
+
document.getElementById('historyTitle').textContent = i18next.t('historyTitle');
|
232 |
document.getElementById('noHistoryMessage').textContent = i18next.t('noHistoryMessage');
|
233 |
+
|
234 |
+
// 置換設定の翻訳を更新
|
235 |
+
document.getElementById('replacementTitle').textContent = i18next.t('replacementTitle');
|
236 |
+
document.getElementById('addReplacementButtonText').textContent = i18next.t('addReplacementButtonText');
|
237 |
+
|
238 |
+
// 既存の置換セットのプレースホルダーを更新
|
239 |
+
document.querySelectorAll('.replacement-search').forEach(el => {
|
240 |
+
el.placeholder = i18next.t('replacementSearchPlaceholder');
|
241 |
+
});
|
242 |
+
document.querySelectorAll('.replacement-replace').forEach(el => {
|
243 |
+
el.placeholder = i18next.t('replacementReplacePlaceholder');
|
244 |
+
});
|
245 |
}
|
246 |
|
247 |
// 言語切り替え関数
|