Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
node-version: '20'
cache: 'npm'

- name: Install dependencies
Expand Down
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@ output
.gemini
.next
images
build_output.txt
build_output.txt

# Test output files
output_test.jpg
output_test.png
25 changes: 20 additions & 5 deletions services/geminiService.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { GoogleGenAI, Type, GenerateContentResponse } from "@google/genai";
import { TranslationBlock } from '../types';

// Helper to get an initialized AI instance
const getAiClient = (customApiKey?: string) => {
const apiKey = customApiKey || (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_GEMINI_API_KEY : undefined);
if (!apiKey) {
Expand All @@ -10,6 +9,13 @@ const getAiClient = (customApiKey?: string) => {
return new GoogleGenAI({ apiKey });
};

const isTranslationBlockArray = (data: unknown): data is TranslationBlock[] => {
return Array.isArray(data) && data.every(item =>
typeof item === 'object' && item !== null &&
'japaneseText' in item && 'englishText' in item && 'boundingBox' in item
);
};

const responseSchema = {
type: Type.ARRAY,
items: {
Expand Down Expand Up @@ -74,10 +80,17 @@ export const translateImageText = async (base64Image: string, mimeType: string,

const jsonText = response.text.trim();
const parsedJson = JSON.parse(jsonText);
return parsedJson as TranslationBlock[];

if (!isTranslationBlockArray(parsedJson)) {
throw new Error("APIレスポンスの形式が無効です。");
}

return parsedJson;

} catch (error) {
console.error("Error calling Gemini API:", error);
if (process.env.NODE_ENV === 'development') {
console.error("Error calling Gemini API:", error);
}
throw new Error("画像の翻訳に失敗しました。API呼び出しでエラーが発生しました。");
}
};
Expand Down Expand Up @@ -113,7 +126,9 @@ export const generateImageSummary = async (base64Image: string, mimeType: string
return response.text.trim();

} catch (error) {
console.error("Error generating image summary:", error);
if (process.env.NODE_ENV === 'development') {
console.error("Error generating image summary:", error);
}
return "翻訳済み画像";
}
};
};
Loading