Spaces:
Running
Running
Upload 6 files
Browse files- control.js +12 -0
- history.js +56 -11
- index.html +27 -27
- prompt.js +10 -3
- translation.js +37 -8
control.js
CHANGED
@@ -20,3 +20,15 @@ document.getElementById('sidebarToggle').addEventListener('click', function () {
|
|
20 |
document.getElementById('sidebar').classList.toggle('active');
|
21 |
document.getElementById('content').classList.toggle('active');
|
22 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
document.getElementById('sidebar').classList.toggle('active');
|
21 |
document.getElementById('content').classList.toggle('active');
|
22 |
});
|
23 |
+
|
24 |
+
function resizeQueryTextarea() {
|
25 |
+
const queryTextarea = document.getElementById('query');
|
26 |
+
const cardBody = queryTextarea.closest('.card-body');
|
27 |
+
queryTextarea.style.minHeight = cardBody.offsetHeight + 'px';
|
28 |
+
}
|
29 |
+
|
30 |
+
document.addEventListener('DOMContentLoaded', function () {
|
31 |
+
resizeQueryTextarea();
|
32 |
+
});
|
33 |
+
|
34 |
+
window.addEventListener('resize', resizeQueryTextarea);
|
history.js
CHANGED
@@ -1,15 +1,22 @@
|
|
1 |
-
function saveToHistory() {
|
|
|
|
|
|
|
2 |
const historyItem = {
|
3 |
query: document.getElementById('query').value,
|
4 |
promptEn: document.getElementById('promptEn').value,
|
5 |
promptMyLanguage: document.getElementById('promptMyLanguage').value,
|
6 |
danbooruTags: document.getElementById('danbooruTags').value,
|
7 |
-
timestamp: new Date().toISOString()
|
|
|
8 |
};
|
9 |
|
10 |
let history = JSON.parse(localStorage.getItem('gemini_prompt_history') || '[]');
|
11 |
history.unshift(historyItem);
|
12 |
-
|
|
|
|
|
|
|
13 |
localStorage.setItem('gemini_prompt_history', JSON.stringify(history));
|
14 |
|
15 |
updateHistoryList();
|
@@ -34,21 +41,31 @@ function updateHistoryList() {
|
|
34 |
|
35 |
const contentDiv = document.createElement('div');
|
36 |
contentDiv.className = 'ms-2 me-auto';
|
37 |
-
contentDiv.style.width = 'calc(100% - 40px)';
|
38 |
contentDiv.style.cursor = 'pointer';
|
39 |
contentDiv.onclick = () => loadHistoryItem(index);
|
40 |
|
41 |
-
const
|
42 |
-
|
43 |
-
|
44 |
|
45 |
const dateDiv = document.createElement('div');
|
46 |
dateDiv.className = 'small text-muted';
|
47 |
dateDiv.textContent = new Date(item.timestamp).toLocaleString();
|
48 |
|
49 |
-
contentDiv.appendChild(
|
50 |
contentDiv.appendChild(dateDiv);
|
51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
const deleteButton = document.createElement('button');
|
53 |
deleteButton.className = 'btn btn-danger btn-sm';
|
54 |
deleteButton.innerHTML = '<i class="fas fa-trash"></i>';
|
@@ -57,9 +74,14 @@ function updateHistoryList() {
|
|
57 |
deleteHistoryItem(index);
|
58 |
};
|
59 |
|
|
|
|
|
|
|
60 |
li.appendChild(contentDiv);
|
61 |
-
li.appendChild(
|
62 |
historyList.appendChild(li);
|
|
|
|
|
63 |
});
|
64 |
}
|
65 |
}
|
@@ -93,10 +115,19 @@ function clearHistory() {
|
|
93 |
function createHistoryItem(item, index) {
|
94 |
const li = document.createElement('li');
|
95 |
li.className = 'list-group-item d-flex justify-content-between align-items-center';
|
96 |
-
|
|
|
|
|
|
|
|
|
97 |
|
98 |
const buttonsContainer = document.createElement('div');
|
99 |
|
|
|
|
|
|
|
|
|
|
|
100 |
const useButton = document.createElement('button');
|
101 |
useButton.className = 'btn btn-sm btn-primary me-2';
|
102 |
useButton.innerHTML = '<i class="fas fa-redo"></i>';
|
@@ -106,15 +137,29 @@ function createHistoryItem(item, index) {
|
|
106 |
deleteButton.className = 'btn btn-sm btn-danger';
|
107 |
deleteButton.innerHTML = '<i class="fas fa-trash"></i>';
|
108 |
deleteButton.onclick = () => {
|
109 |
-
// 個別の履歴項目削除時にも確認ポップアップを表示
|
110 |
if (confirm('この履歴項目を削除してもよろしいですか?')) {
|
111 |
deleteHistoryItem(index);
|
112 |
}
|
113 |
};
|
114 |
|
|
|
115 |
buttonsContainer.appendChild(useButton);
|
116 |
buttonsContainer.appendChild(deleteButton);
|
117 |
li.appendChild(buttonsContainer);
|
118 |
|
119 |
return li;
|
120 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function saveToHistory(title) {
|
2 |
+
if(!title) {
|
3 |
+
title = document.getElementById('query').value.slice(0, 10);
|
4 |
+
}
|
5 |
const historyItem = {
|
6 |
query: document.getElementById('query').value,
|
7 |
promptEn: document.getElementById('promptEn').value,
|
8 |
promptMyLanguage: document.getElementById('promptMyLanguage').value,
|
9 |
danbooruTags: document.getElementById('danbooruTags').value,
|
10 |
+
timestamp: new Date().toISOString(),
|
11 |
+
title: title
|
12 |
};
|
13 |
|
14 |
let history = JSON.parse(localStorage.getItem('gemini_prompt_history') || '[]');
|
15 |
history.unshift(historyItem);
|
16 |
+
// 履歴の合計サイズが3MB以下になるまで古い項目を削除
|
17 |
+
while (JSON.stringify(history).length > 3 * 1024 * 1024) {
|
18 |
+
history.pop();
|
19 |
+
}
|
20 |
localStorage.setItem('gemini_prompt_history', JSON.stringify(history));
|
21 |
|
22 |
updateHistoryList();
|
|
|
41 |
|
42 |
const contentDiv = document.createElement('div');
|
43 |
contentDiv.className = 'ms-2 me-auto';
|
|
|
44 |
contentDiv.style.cursor = 'pointer';
|
45 |
contentDiv.onclick = () => loadHistoryItem(index);
|
46 |
|
47 |
+
const titleDiv = document.createElement('div');
|
48 |
+
titleDiv.className = 'fw-bold text-truncate';
|
49 |
+
titleDiv.textContent = item.title || item.query.slice(0, 10);
|
50 |
|
51 |
const dateDiv = document.createElement('div');
|
52 |
dateDiv.className = 'small text-muted';
|
53 |
dateDiv.textContent = new Date(item.timestamp).toLocaleString();
|
54 |
|
55 |
+
contentDiv.appendChild(titleDiv);
|
56 |
contentDiv.appendChild(dateDiv);
|
57 |
|
58 |
+
const buttonsContainer = document.createElement('div');
|
59 |
+
buttonsContainer.className = 'd-flex';
|
60 |
+
|
61 |
+
const editButton = document.createElement('button');
|
62 |
+
editButton.className = 'btn btn-secondary btn-sm me-2';
|
63 |
+
editButton.innerHTML = '<i class="fas fa-pencil-alt"></i>';
|
64 |
+
editButton.onclick = (e) => {
|
65 |
+
e.stopPropagation();
|
66 |
+
editHistoryItemTitle(index, titleDiv);
|
67 |
+
};
|
68 |
+
|
69 |
const deleteButton = document.createElement('button');
|
70 |
deleteButton.className = 'btn btn-danger btn-sm';
|
71 |
deleteButton.innerHTML = '<i class="fas fa-trash"></i>';
|
|
|
74 |
deleteHistoryItem(index);
|
75 |
};
|
76 |
|
77 |
+
buttonsContainer.appendChild(editButton);
|
78 |
+
buttonsContainer.appendChild(deleteButton);
|
79 |
+
|
80 |
li.appendChild(contentDiv);
|
81 |
+
li.appendChild(buttonsContainer);
|
82 |
historyList.appendChild(li);
|
83 |
+
|
84 |
+
contentDiv.style.width = `calc(100% - ${buttonsContainer.offsetWidth}px)`;
|
85 |
});
|
86 |
}
|
87 |
}
|
|
|
115 |
function createHistoryItem(item, index) {
|
116 |
const li = document.createElement('li');
|
117 |
li.className = 'list-group-item d-flex justify-content-between align-items-center';
|
118 |
+
|
119 |
+
const titleSpan = document.createElement('span');
|
120 |
+
titleSpan.textContent = item.title || item.query.slice(0, 10);
|
121 |
+
titleSpan.className = 'me-2';
|
122 |
+
li.appendChild(titleSpan);
|
123 |
|
124 |
const buttonsContainer = document.createElement('div');
|
125 |
|
126 |
+
const editButton = document.createElement('button');
|
127 |
+
editButton.className = 'btn btn-sm btn-secondary me-2';
|
128 |
+
editButton.innerHTML = '<i class="fas fa-pencil-alt"></i>';
|
129 |
+
editButton.onclick = () => editHistoryItemTitle(index, titleSpan);
|
130 |
+
|
131 |
const useButton = document.createElement('button');
|
132 |
useButton.className = 'btn btn-sm btn-primary me-2';
|
133 |
useButton.innerHTML = '<i class="fas fa-redo"></i>';
|
|
|
137 |
deleteButton.className = 'btn btn-sm btn-danger';
|
138 |
deleteButton.innerHTML = '<i class="fas fa-trash"></i>';
|
139 |
deleteButton.onclick = () => {
|
|
|
140 |
if (confirm('この履歴項目を削除してもよろしいですか?')) {
|
141 |
deleteHistoryItem(index);
|
142 |
}
|
143 |
};
|
144 |
|
145 |
+
buttonsContainer.appendChild(editButton);
|
146 |
buttonsContainer.appendChild(useButton);
|
147 |
buttonsContainer.appendChild(deleteButton);
|
148 |
li.appendChild(buttonsContainer);
|
149 |
|
150 |
return li;
|
151 |
}
|
152 |
+
|
153 |
+
function editHistoryItemTitle(index, titleDiv) {
|
154 |
+
const history = JSON.parse(localStorage.getItem('gemini_prompt_history') || '[]');
|
155 |
+
const item = history[index];
|
156 |
+
const currentTitle = item.title || item.query.slice(0, 10);
|
157 |
+
|
158 |
+
const newTitle = prompt('新しいタイトルを入力してください:', currentTitle);
|
159 |
+
if (newTitle !== null && newTitle.trim() !== '') {
|
160 |
+
item.title = newTitle.trim();
|
161 |
+
history[index] = item;
|
162 |
+
localStorage.setItem('gemini_prompt_history', JSON.stringify(history));
|
163 |
+
titleDiv.textContent = newTitle.trim();
|
164 |
+
}
|
165 |
+
}
|
index.html
CHANGED
@@ -9,20 +9,14 @@
|
|
9 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
|
10 |
crossorigin="anonymous">
|
11 |
<style>
|
12 |
-
|
13 |
-
min-height:
|
14 |
}
|
15 |
-
|
16 |
-
#promptEn,
|
17 |
-
#promptMyLanguage {
|
18 |
-
min-height: 20vh;
|
19 |
-
}
|
20 |
-
|
21 |
#sidebar {
|
22 |
position: fixed;
|
23 |
top: 0;
|
24 |
-
left: -
|
25 |
-
width:
|
26 |
height: 100%;
|
27 |
background-color: #343a40;
|
28 |
transition: 0.3s;
|
@@ -35,12 +29,18 @@
|
|
35 |
|
36 |
#content {
|
37 |
transition: margin-left 0.3s;
|
|
|
38 |
}
|
39 |
|
40 |
#content.active {
|
41 |
margin-left: 250px;
|
42 |
}
|
43 |
|
|
|
|
|
|
|
|
|
|
|
44 |
#historyContainer::-webkit-scrollbar {
|
45 |
width: 5px;
|
46 |
}
|
@@ -81,6 +81,10 @@
|
|
81 |
width: 100%;
|
82 |
height: auto;
|
83 |
}
|
|
|
|
|
|
|
|
|
84 |
}
|
85 |
|
86 |
@keyframes comic-frame-switch {
|
@@ -104,7 +108,6 @@
|
|
104 |
<h3 id="settingsTitle" class="text-white">設定</h3>
|
105 |
<div class="form-group mb-3">
|
106 |
<label for="apiKey" class="form-label" id="apiKeyLabel">
|
107 |
-
|
108 |
<a href="https://aistudio.google.com/app/apikey?hl=ja" target="_blank">APIキー</a>
|
109 |
</label>
|
110 |
<input type="text" class="form-control" id="apiKey" placeholder="APIキーを入力してください">
|
@@ -134,13 +137,12 @@
|
|
134 |
<option value="gemini-1.5-flash-exp-0827">gemini-1.5-flash-exp-0827</option>
|
135 |
<option value="gemini-1.5-pro-latest">gemini-1.5-pro-latest</option>
|
136 |
<option value="gemini-1.5-flash-latest">gemini-1.5-flash-latest</option>
|
137 |
-
|
138 |
</select>
|
139 |
</div>
|
140 |
|
141 |
<h3 class="text-white mt-4">履歴</h3>
|
142 |
-
<div id="historyContainer"
|
143 |
-
<ul id="historyList" class="list-group">
|
144 |
<!-- 履歴項目がここに動的に追加されます -->
|
145 |
</ul>
|
146 |
<p id="noHistoryMessage" class="text-white mt-2 d-none">履歴がありません。</p>
|
@@ -149,7 +151,7 @@
|
|
149 |
<!-- デバッグ用のモーダル表示ボタンを追加 -->
|
150 |
<div class="mt-4">
|
151 |
<button id="showLoadingModalButton" class="btn btn-secondary w-100">
|
152 |
-
|
153 |
</button>
|
154 |
</div>
|
155 |
</div>
|
@@ -157,7 +159,7 @@
|
|
157 |
|
158 |
<div id="content">
|
159 |
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
160 |
-
<div class="container
|
161 |
<button id="sidebarToggle" class="btn btn-outline-light me-2">
|
162 |
<i class="fas fa-bars"></i>
|
163 |
</button>
|
@@ -167,8 +169,8 @@
|
|
167 |
|
168 |
<div class="container mt-3">
|
169 |
<div class="row">
|
170 |
-
<div id="inputQuery" class="col-md-
|
171 |
-
<div class="card">
|
172 |
<div class="card-header bg-primary text-white">
|
173 |
<h5 class="mb-0" id="inputQueryTitle">入力クエリ</h5>
|
174 |
</div>
|
@@ -192,26 +194,25 @@
|
|
192 |
</div>
|
193 |
</div>
|
194 |
</div>
|
195 |
-
<div id="outputPrompt" class="col-md-
|
196 |
-
<div class="card">
|
197 |
<div class="card-header bg-success text-white">
|
198 |
<h5 class="mb-0" id="outputPromptTitle">生成されたプロンプト</h5>
|
199 |
</div>
|
200 |
<div class="card-body">
|
201 |
<div class="form-group">
|
202 |
-
<
|
203 |
-
|
204 |
</div>
|
205 |
<div class="form-group mt-3">
|
206 |
-
<
|
207 |
-
|
208 |
</div>
|
209 |
<div class="form-group mt-3">
|
210 |
<label for="danbooruTags" class="form-label" id="danbooruTagsLabel">
|
211 |
danbooru tags
|
212 |
</label>
|
213 |
-
<input type="text" class="form-control" id="danbooruTags" placeholder="danbooru tags"
|
214 |
-
readonly>
|
215 |
</div>
|
216 |
</div>
|
217 |
</div>
|
@@ -251,7 +252,6 @@
|
|
251 |
|
252 |
<script>
|
253 |
document.getElementById('showLoadingModalButton').addEventListener('click', function () {
|
254 |
-
|
255 |
var loadingModal = new bootstrap.Modal(document.getElementById('loadingModal'));
|
256 |
loadingModal.show();
|
257 |
});
|
|
|
9 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
|
10 |
crossorigin="anonymous">
|
11 |
<style>
|
12 |
+
textarea.form-control {
|
13 |
+
min-height: 15vh;
|
14 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
#sidebar {
|
16 |
position: fixed;
|
17 |
top: 0;
|
18 |
+
left: -16em;
|
19 |
+
width: 16rem;
|
20 |
height: 100%;
|
21 |
background-color: #343a40;
|
22 |
transition: 0.3s;
|
|
|
29 |
|
30 |
#content {
|
31 |
transition: margin-left 0.3s;
|
32 |
+
min-height: 100vh;
|
33 |
}
|
34 |
|
35 |
#content.active {
|
36 |
margin-left: 250px;
|
37 |
}
|
38 |
|
39 |
+
#historyContainer {
|
40 |
+
max-height: 300px;
|
41 |
+
overflow-y: auto;
|
42 |
+
}
|
43 |
+
|
44 |
#historyContainer::-webkit-scrollbar {
|
45 |
width: 5px;
|
46 |
}
|
|
|
81 |
width: 100%;
|
82 |
height: auto;
|
83 |
}
|
84 |
+
.form-group {
|
85 |
+
padding-left: 1rem;
|
86 |
+
padding-right: 1rem;
|
87 |
+
}
|
88 |
}
|
89 |
|
90 |
@keyframes comic-frame-switch {
|
|
|
108 |
<h3 id="settingsTitle" class="text-white">設定</h3>
|
109 |
<div class="form-group mb-3">
|
110 |
<label for="apiKey" class="form-label" id="apiKeyLabel">
|
|
|
111 |
<a href="https://aistudio.google.com/app/apikey?hl=ja" target="_blank">APIキー</a>
|
112 |
</label>
|
113 |
<input type="text" class="form-control" id="apiKey" placeholder="APIキーを入力してください">
|
|
|
137 |
<option value="gemini-1.5-flash-exp-0827">gemini-1.5-flash-exp-0827</option>
|
138 |
<option value="gemini-1.5-pro-latest">gemini-1.5-pro-latest</option>
|
139 |
<option value="gemini-1.5-flash-latest">gemini-1.5-flash-latest</option>
|
|
|
140 |
</select>
|
141 |
</div>
|
142 |
|
143 |
<h3 class="text-white mt-4">履歴</h3>
|
144 |
+
<div id="historyContainer">
|
145 |
+
<ul id="historyList" class="list-group small">
|
146 |
<!-- 履歴項目がここに動的に追加されます -->
|
147 |
</ul>
|
148 |
<p id="noHistoryMessage" class="text-white mt-2 d-none">履歴がありません。</p>
|
|
|
151 |
<!-- デバッグ用のモーダル表示ボタンを追加 -->
|
152 |
<div class="mt-4">
|
153 |
<button id="showLoadingModalButton" class="btn btn-secondary w-100">
|
154 |
+
Show Modal
|
155 |
</button>
|
156 |
</div>
|
157 |
</div>
|
|
|
159 |
|
160 |
<div id="content">
|
161 |
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
162 |
+
<div class="container">
|
163 |
<button id="sidebarToggle" class="btn btn-outline-light me-2">
|
164 |
<i class="fas fa-bars"></i>
|
165 |
</button>
|
|
|
169 |
|
170 |
<div class="container mt-3">
|
171 |
<div class="row">
|
172 |
+
<div id="inputQuery" class="col-lg-4 col-md-12 mb-4">
|
173 |
+
<div class="card h-100">
|
174 |
<div class="card-header bg-primary text-white">
|
175 |
<h5 class="mb-0" id="inputQueryTitle">入力クエリ</h5>
|
176 |
</div>
|
|
|
194 |
</div>
|
195 |
</div>
|
196 |
</div>
|
197 |
+
<div id="outputPrompt" class="col-lg-8 col-md-12 mb-4">
|
198 |
+
<div class="card h-100">
|
199 |
<div class="card-header bg-success text-white">
|
200 |
<h5 class="mb-0" id="outputPromptTitle">生成されたプロンプト</h5>
|
201 |
</div>
|
202 |
<div class="card-body">
|
203 |
<div class="form-group">
|
204 |
+
<label for="promptEn" class="form-label" id="promptEnLabel">English Prompt</label>
|
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 Language Translation</label>
|
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" readonly>
|
|
|
216 |
</div>
|
217 |
</div>
|
218 |
</div>
|
|
|
252 |
|
253 |
<script>
|
254 |
document.getElementById('showLoadingModalButton').addEventListener('click', function () {
|
|
|
255 |
var loadingModal = new bootstrap.Modal(document.getElementById('loadingModal'));
|
256 |
loadingModal.show();
|
257 |
});
|
prompt.js
CHANGED
@@ -17,7 +17,8 @@ function generatePrompt() {
|
|
17 |
anotherLanguage = `,
|
18 |
{
|
19 |
"language": "${i18next.language}",
|
20 |
-
"text": ${textFormat}
|
|
|
21 |
}`;
|
22 |
}
|
23 |
|
@@ -34,6 +35,7 @@ function generatePrompt() {
|
|
34 |
{
|
35 |
"language": "en",
|
36 |
"text": ${textFormat} # ${document.getElementById('characterCount').value}文字程度,
|
|
|
37 |
},
|
38 |
{
|
39 |
"language": "danbooru",
|
@@ -41,7 +43,8 @@ function generatePrompt() {
|
|
41 |
},
|
42 |
{
|
43 |
"language": "ja",
|
44 |
-
"text": ${textFormat}
|
|
|
45 |
}${anotherLanguage}
|
46 |
]
|
47 |
}
|
@@ -123,14 +126,17 @@ function generatePrompt() {
|
|
123 |
document.getElementById('danbooruTags').value = danbooruTags.join(", ");
|
124 |
}
|
125 |
|
|
|
126 |
|
127 |
// ローディングアイコンを非表示
|
128 |
document.getElementById('loading').classList.add('d-none');
|
129 |
document.getElementById('generatePromptButton').disabled = false;
|
130 |
document.getElementById('generatePromptButton').classList.remove('btn-secondary');
|
131 |
document.getElementById('generatePromptButton').classList.add('btn-primary');
|
|
|
|
|
132 |
saveToUserStorage(true);
|
133 |
-
saveToHistory(); // 履歴に保存
|
134 |
})
|
135 |
.catch(error => {
|
136 |
console.error(error);
|
@@ -139,6 +145,7 @@ function generatePrompt() {
|
|
139 |
document.getElementById('generatePromptButton').classList.add('btn-danger');
|
140 |
})
|
141 |
.finally(() => {
|
|
|
142 |
// ローディングアイコンを非表示
|
143 |
document.getElementById('loading').classList.add('d-none');
|
144 |
document.getElementById('generatePromptButton').disabled = false;
|
|
|
17 |
anotherLanguage = `,
|
18 |
{
|
19 |
"language": "${i18next.language}",
|
20 |
+
"text": ${textFormat},
|
21 |
+
"title": str
|
22 |
}`;
|
23 |
}
|
24 |
|
|
|
35 |
{
|
36 |
"language": "en",
|
37 |
"text": ${textFormat} # ${document.getElementById('characterCount').value}文字程度,
|
38 |
+
"title": str
|
39 |
},
|
40 |
{
|
41 |
"language": "danbooru",
|
|
|
43 |
},
|
44 |
{
|
45 |
"language": "ja",
|
46 |
+
"text": ${textFormat},
|
47 |
+
"title": str
|
48 |
}${anotherLanguage}
|
49 |
]
|
50 |
}
|
|
|
126 |
document.getElementById('danbooruTags').value = danbooruTags.join(", ");
|
127 |
}
|
128 |
|
129 |
+
const title = parsedData.results.find(x => x.language === i18next.language).title;
|
130 |
|
131 |
// ローディングアイコンを非表示
|
132 |
document.getElementById('loading').classList.add('d-none');
|
133 |
document.getElementById('generatePromptButton').disabled = false;
|
134 |
document.getElementById('generatePromptButton').classList.remove('btn-secondary');
|
135 |
document.getElementById('generatePromptButton').classList.add('btn-primary');
|
136 |
+
|
137 |
+
document.getElementById('query').value = query;
|
138 |
saveToUserStorage(true);
|
139 |
+
saveToHistory(title); // 履歴に保存
|
140 |
})
|
141 |
.catch(error => {
|
142 |
console.error(error);
|
|
|
145 |
document.getElementById('generatePromptButton').classList.add('btn-danger');
|
146 |
})
|
147 |
.finally(() => {
|
148 |
+
document.getElementById('query').value = query;
|
149 |
// ローディングアイコンを非表示
|
150 |
document.getElementById('loading').classList.add('d-none');
|
151 |
document.getElementById('generatePromptButton').disabled = false;
|
translation.js
CHANGED
@@ -11,7 +11,10 @@ const translations = {
|
|
11 |
promptEnPlaceholder: "英語のプロンプトがここに表示されます",
|
12 |
promptMyLanguagePlaceholder: "日本訳がここに表示されます",
|
13 |
apiKeyPlaceholder: "APIキーを入力してください",
|
14 |
-
characterCountPlaceholder: "生成するプロンプトの文字数を入力してください"
|
|
|
|
|
|
|
15 |
},
|
16 |
en: {
|
17 |
inputQueryTitle: "Input Query",
|
@@ -25,7 +28,10 @@ const translations = {
|
|
25 |
promptEnPlaceholder: "English prompt will be displayed here",
|
26 |
promptMyLanguagePlaceholder: "Translation will be displayed here",
|
27 |
apiKeyPlaceholder: "Enter your API key",
|
28 |
-
characterCountPlaceholder: "Enter the number of characters for the generated prompt"
|
|
|
|
|
|
|
29 |
},
|
30 |
zh: {
|
31 |
inputQueryTitle: "输入查询",
|
@@ -39,7 +45,10 @@ const translations = {
|
|
39 |
promptEnPlaceholder: "英文提示将显示在这里",
|
40 |
promptMyLanguagePlaceholder: "翻译将显示在这里",
|
41 |
apiKeyPlaceholder: "请输入您的API密钥",
|
42 |
-
characterCountPlaceholder: "请输入生成提示的字符数"
|
|
|
|
|
|
|
43 |
},
|
44 |
ko: {
|
45 |
inputQueryTitle: "입력 쿼리",
|
@@ -53,7 +62,10 @@ const translations = {
|
|
53 |
promptEnPlaceholder: "영어 프롬프트가 여기에 표시됩니다",
|
54 |
promptMyLanguagePlaceholder: "번역이 여기에 표시됩니다",
|
55 |
apiKeyPlaceholder: "API 키를 입력하세요",
|
56 |
-
characterCountPlaceholder: "생성할 프롬프트의 문자 수를 입력하세요"
|
|
|
|
|
|
|
57 |
},
|
58 |
fr: {
|
59 |
inputQueryTitle: "Requête d'entrée",
|
@@ -67,7 +79,10 @@ const translations = {
|
|
67 |
promptEnPlaceholder: "Le prompt en anglais s'affichera ici",
|
68 |
promptMyLanguagePlaceholder: "La traduction s'affichera ici",
|
69 |
apiKeyPlaceholder: "Entrez votre clé API",
|
70 |
-
characterCountPlaceholder: "Entrez le nombre de caractères pour le prompt généré"
|
|
|
|
|
|
|
71 |
},
|
72 |
es: {
|
73 |
inputQueryTitle: "Consulta de entrada",
|
@@ -81,7 +96,10 @@ const translations = {
|
|
81 |
promptEnPlaceholder: "El prompt en inglés se mostrará aquí",
|
82 |
promptMyLanguagePlaceholder: "La traducción se mostrará aquí",
|
83 |
apiKeyPlaceholder: "Ingrese su clave API",
|
84 |
-
characterCountPlaceholder: "Ingrese el número de caracteres para el prompt generado"
|
|
|
|
|
|
|
85 |
},
|
86 |
de: {
|
87 |
inputQueryTitle: "Eingabeabfrage",
|
@@ -95,7 +113,10 @@ const translations = {
|
|
95 |
promptEnPlaceholder: "Der englische Prompt wird hier angezeigt",
|
96 |
promptMyLanguagePlaceholder: "Die Übersetzung wird hier angezeigt",
|
97 |
apiKeyPlaceholder: "Geben Sie Ihren API-Schlüssel ein",
|
98 |
-
characterCountPlaceholder: "Geben Sie die Anzahl der Zeichen für den generierten Prompt ein"
|
|
|
|
|
|
|
99 |
},
|
100 |
it: {
|
101 |
inputQueryTitle: "Query di input",
|
@@ -109,7 +130,10 @@ const translations = {
|
|
109 |
promptEnPlaceholder: "Il prompt in inglese verrà visualizzato qui",
|
110 |
promptMyLanguagePlaceholder: "La traduzione verrà visualizzata qui",
|
111 |
apiKeyPlaceholder: "Inserisci la tua chiave API",
|
112 |
-
characterCountPlaceholder: "Inserisci il numero di caratteri per il prompt generato"
|
|
|
|
|
|
|
113 |
}
|
114 |
}
|
115 |
const resources = {
|
@@ -169,6 +193,11 @@ function updateContent() {
|
|
169 |
document.getElementById('promptMyLanguage').placeholder = i18next.t('promptMyLanguagePlaceholder');
|
170 |
document.getElementById('apiKey').placeholder = i18next.t('apiKeyPlaceholder');
|
171 |
document.getElementById('characterCount').placeholder = i18next.t('characterCountPlaceholder');
|
|
|
|
|
|
|
|
|
|
|
172 |
}
|
173 |
|
174 |
// 言語切り替え関数
|
|
|
11 |
promptEnPlaceholder: "英語のプロンプトがここに表示されます",
|
12 |
promptMyLanguagePlaceholder: "日本訳がここに表示されます",
|
13 |
apiKeyPlaceholder: "APIキーを入力してください",
|
14 |
+
characterCountPlaceholder: "生成するプロンプトの文字数を入力してください",
|
15 |
+
endpointSelectLabel: "エンドポイント",
|
16 |
+
historyTitle: "履歴",
|
17 |
+
noHistoryMessage: "履歴がありません。"
|
18 |
},
|
19 |
en: {
|
20 |
inputQueryTitle: "Input Query",
|
|
|
28 |
promptEnPlaceholder: "English prompt will be displayed here",
|
29 |
promptMyLanguagePlaceholder: "Translation will be displayed here",
|
30 |
apiKeyPlaceholder: "Enter your API key",
|
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: "输入查询",
|
|
|
45 |
promptEnPlaceholder: "英文提示将显示在这里",
|
46 |
promptMyLanguagePlaceholder: "翻译将显示在这里",
|
47 |
apiKeyPlaceholder: "请输入您的API密钥",
|
48 |
+
characterCountPlaceholder: "请输入生成提示的字符数",
|
49 |
+
endpointSelectLabel: "端点",
|
50 |
+
historyTitle: "历史记录",
|
51 |
+
noHistoryMessage: "没有可用的历史记录。"
|
52 |
},
|
53 |
ko: {
|
54 |
inputQueryTitle: "입력 쿼리",
|
|
|
62 |
promptEnPlaceholder: "영어 프롬프트가 여기에 표시됩니다",
|
63 |
promptMyLanguagePlaceholder: "번역이 여기에 표시됩니다",
|
64 |
apiKeyPlaceholder: "API 키를 입력하세요",
|
65 |
+
characterCountPlaceholder: "생성할 프롬프트의 문자 수를 입력하세요",
|
66 |
+
endpointSelectLabel: "엔드포인트",
|
67 |
+
historyTitle: "기록",
|
68 |
+
noHistoryMessage: "사용 가능한 기록이 없습니다."
|
69 |
},
|
70 |
fr: {
|
71 |
inputQueryTitle: "Requête d'entrée",
|
|
|
79 |
promptEnPlaceholder: "Le prompt en anglais s'affichera ici",
|
80 |
promptMyLanguagePlaceholder: "La traduction s'affichera ici",
|
81 |
apiKeyPlaceholder: "Entrez votre clé API",
|
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",
|
|
|
96 |
promptEnPlaceholder: "El prompt en inglés se mostrará aquí",
|
97 |
promptMyLanguagePlaceholder: "La traducción se mostrará aquí",
|
98 |
apiKeyPlaceholder: "Ingrese su clave API",
|
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",
|
|
|
113 |
promptEnPlaceholder: "Der englische Prompt wird hier angezeigt",
|
114 |
promptMyLanguagePlaceholder: "Die Übersetzung wird hier angezeigt",
|
115 |
apiKeyPlaceholder: "Geben Sie Ihren API-Schlüssel ein",
|
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",
|
|
|
130 |
promptEnPlaceholder: "Il prompt in inglese verrà visualizzato qui",
|
131 |
promptMyLanguagePlaceholder: "La traduzione verrà visualizzata qui",
|
132 |
apiKeyPlaceholder: "Inserisci la tua chiave API",
|
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 = {
|
|
|
193 |
document.getElementById('promptMyLanguage').placeholder = i18next.t('promptMyLanguagePlaceholder');
|
194 |
document.getElementById('apiKey').placeholder = i18next.t('apiKeyPlaceholder');
|
195 |
document.getElementById('characterCount').placeholder = i18next.t('characterCountPlaceholder');
|
196 |
+
|
197 |
+
// エンドポイントと履歴のテキストを更新
|
198 |
+
document.getElementById('endpointSelectLabel').textContent = i18next.t('endpointSelectLabel');
|
199 |
+
document.querySelector('#sidebar h3:nth-of-type(2)').textContent = i18next.t('historyTitle');
|
200 |
+
document.getElementById('noHistoryMessage').textContent = i18next.t('noHistoryMessage');
|
201 |
}
|
202 |
|
203 |
// 言語切り替え関数
|