0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Sunoのプロンプトが200文字までなので、DeepL API & 文字数カウンターを作ってみた

Posted at

はじめに

DeepL API & 文字数カウンター
https://gist.github.com/sarap422/b2c0fdff98b14197cc7fd41541b5cf34

Sunoのプロンプトは200文字までという制限があります。長文を分割するのは手間がかかるので、文字数をカウントしながら翻訳できるツールを作ってみました。DeepL API Freeを使用することで、月50万文字まで無料で高精度な翻訳が利用できます。

DeepL API Freeの特徴

  • 月間50万文字まで無料
  • 高精度な機械翻訳
  • シンプルなAPI
  • 多言語対応(28言語以上)
  • セキュアな通信(HTTPS必須)

実装手順

1. DeepL API Freeのアカウント作成

  1. DeepL API Freeにアクセス
  2. アカウントを作成
  3. APIキーを取得(形式: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:fx

2. CORSの問題を解決するためのプロキシ作成

ブラウザから直接DeepL APIを呼び出すとCORSエラーが発生するため、PHPでプロキシを作成します。

<?php
// translation-proxy.php

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
header('Content-Type: application/json; charset=utf-8');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit();
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['error' => 'Method not allowed']);
    exit();
}

$json = file_get_contents('php://input');
$data = json_decode($json, true);

if (!isset($data['text']) || !isset($data['source_lang']) || 
    !isset($data['target_lang']) || !isset($data['api_key'])) {
    http_response_code(400);
    echo json_encode(['error' => 'Missing required parameters']);
    exit();
}

$url = 'https://api-free.deepl.com/v2/translate';
$params = http_build_query([
    'text' => $data['text'],
    'source_lang' => $data['source_lang'],
    'target_lang' => $data['target_lang']
]);

$ch = curl_init();

curl_setopt_array($ch, [
    CURLOPT_URL => $url,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $params,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: DeepL-Auth-Key ' . $data['api_key'],
        'Content-Type: application/x-www-form-urlencoded'
    ],
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_TIMEOUT => 30
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if (curl_errno($ch)) {
    http_response_code(500);
    echo json_encode(['error' => 'Curl error: ' . curl_error($ch)]);
    curl_close($ch);
    exit();
}

curl_close($ch);
http_response_code($httpCode);
echo $response;

3. フロントエンド実装

HTMLでUIを作成し、JavaScriptで文字数カウントと翻訳機能を実装します。

<div class="translation-container">
  <div class="api-key-section">
    <label for="api-key">DeepL API Key:</label>
    <input type="text" id="api-key">
  </div>

  <div class="language-selection">
    <select id="source-lang">
      <option value="JA">日本語</option>
      <option value="EN">英語</option>
      <option value="IT">イタリア語</option>
      <option value="FR">フランス語</option>
    </select><select id="target-lang">
      <option value="EN">英語</option>
      <option value="JA">日本語</option>
      <option value="IT">イタリア語</option>
      <option value="FR">フランス語</option>
    </select>
  </div>

  <textarea id="input-text" placeholder="ここにテキストを入力"></textarea>
  
  <div id="count">
    半角文字換算:0文字<br>
    全角文字換算:0文字<br>
    DeepL API Free 残り文字数:500,000文字
  </div>

  <button id="translate-button">翻訳</button>
  <div id="translation-result"></div>
  <div id="error-message"></div>
</div>

4. 主要な機能の実装

// 文字数カウント機能
function countCharacters(text) {
  let fullWidthCount = 0;
  let halfWidthCount = 0;
  for (let char of text) {
    if (char.match(/[^\x00-\xff]/)) {  // 全角文字の判定
      fullWidthCount += 1;
      halfWidthCount += 2;
    } else {
      halfWidthCount += 1;
      fullWidthCount += 0.5;
    }
  }
  return { halfWidth: halfWidthCount, fullWidth: fullWidthCount };
}

// 翻訳機能
async function translateText() {
  // APIキーと入力テキストの取得
  const apiKey = document.getElementById('api-key').value.trim();
  const text = document.getElementById('input-text').value.trim();
  
  // バリデーション
  if (!apiKey || !text) return;

  try {
    const response = await fetch('/path/to/translation-proxy.php', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        text,
        source_lang: document.getElementById('source-lang').value,
        target_lang: document.getElementById('target-lang').value,
        api_key: apiKey
      })
    });

    const data = await response.json();
    if (data.translations) {
      showTranslation(data.translations[0].text);
    }
  } catch (error) {
    showError(error.message);
  }
}

実装のポイント

  1. 文字数カウント

    • 全角/半角を区別してカウント
    • リアルタイムでの更新
    • 月間制限(50万文字)との比較
  2. セキュリティ対策

    • APIキーの保護(プロキシ経由)
    • XSS対策
    • 入力値のバリデーション
  3. UX向上

    • エラーメッセージの表示
    • ローディング状態の表示
    • APIキーの保存(LocalStorage)
  4. 保守性

    • モジュール化されたコード
    • エラーハンドリング
    • コメントによる説明

カスタマイズのヒント

  1. 追加可能な機能

    • 翻訳履歴の保存
    • 文字数制限のアラート
    • ショートカットキー
    • 翻訳結果のコピー機能
  2. スタイリング

    • レスポンシブデザイン
    • ダークモード対応
    • アニメーション効果

注意点

  • DeepL API Freeの利用制限(月間50万文字)を超えないよう注意
  • APIキーは適切に管理(環境変数やconfig管理推奨)
  • プロキシファイルのパーミッション設定に注意
  • HTTPS環境での運用推奨

まとめ

DeepL API Freeを使用することで、高品質な翻訳機能を無料で利用できます。文字数カウンターと組み合わせることで、制限を意識しながら効率的に翻訳作業を行えます。

また、このコードはGitHubで公開されているDeepLの公式クライアントライブラリと互換性があり、必要に応じて拡張することも可能です。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?