[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/UserXSX/JavaGuide/main/TranslateRepo.java [Back]  [Original]

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.*;
import java.util.stream.Collectors;
import com.google.gson.*;

/**
 * Repository Documentation Translation Tool
 * 
 * Translates all markdown files in docs/ folder to target language.
 * Preserves directory structure and saves to docs_{lang}/ folder.
 * 
 * Usage: java TranslateRepo
 */
public class TranslateRepo {
    
    private static final int CHUNK_SIZE = 4000;
    private static final String PROGRESS_FILE = ".translation_progress.json";
    private static final Map LANGUAGES = new LinkedHashMap();
    
    static {
        LANGUAGES.put("1", new Language("English", "en", "en"));
        LANGUAGES.put("2", new Language("Chinese (Simplified)", "zh-CN", "zh"));
        LANGUAGES.put("3", new Language("Spanish", "es", "es"));
        LANGUAGES.put("4", new Language("French", "fr", "fr"));
        LANGUAGES.put("5", new Language("Portuguese", "pt", "pt"));
        LANGUAGES.put("6", new Language("German", "de", "de"));
        LANGUAGES.put("7", new Language("Japanese", "ja", "ja"));
        LANGUAGES.put("8", new Language("Korean", "ko", "ko"));
        LANGUAGES.put("9", new Language("Russian", "ru", "ru"));
        LANGUAGES.put("10", new Language("Italian", "it", "it"));
        LANGUAGES.put("11", new Language("Arabic", "ar", "ar"));
        LANGUAGES.put("12", new Language("Hindi", "hi", "hi"));
        LANGUAGES.put("13", new Language("Turkish", "tr", "tr"));
        LANGUAGES.put("14", new Language("Vietnamese", "vi", "vi"));
        LANGUAGES.put("15", new Language("Polish", "pl", "pl"));
        LANGUAGES.put("16", new Language("Dutch", "nl", "nl"));
        LANGUAGES.put("17", new Language("Indonesian", "id", "id"));
        LANGUAGES.put("18", new Language("Thai", "th", "th"));
        LANGUAGES.put("19", new Language("Swedish", "sv", "sv"));
        LANGUAGES.put("20", new Language("Greek", "el", "el"));
    }
    
    static class Language {
        String name;
        String code;
        String suffix;
        
        Language(String name, String code, String suffix) {
            this.name = name;
            this.code = code;
            this.suffix = suffix;
        }
    }
    
    static class TranslationProgress {
        Set completed = new HashSet();
        Set failed = new HashSet();
    }
    
    public static void main(String[] args) {
        try {
            printHeader();
            
            // Get repository path
            Scanner scanner = new Scanner(System.in);
            System.out.print("Enter repository path (default: current directory): ");
            String repoPathStr = scanner.nextLine().trim();
            if (repoPathStr.isEmpty()) {
                repoPathStr = ".";
            }
            
            Path repoPath = Paths.get(repoPathStr).toAbsolutePath();
            if (!Files.exists(repoPath)) {
                System.out.println(" Repository path does not exist: " + repoPath);
                return;
            }
            
            System.out.println(" Repository: " + repoPath);
            System.out.println();
            
            // Select language
            Language language = selectLanguage(scanner);
            System.out.println("\n Selected: " + language.name);
            System.out.println();
            
            // Find markdown files
            System.out.println(" Finding markdown files...");
            List mdFiles = findMarkdownFiles(repoPath);
            
            if (mdFiles.isEmpty()) {
                System.out.println(" No markdown files found in docs/ folder or README.md");
                return;
            }
            
            System.out.println(" Found " + mdFiles.size() + " markdown files");
            System.out.println();
            
            // Load progress
            TranslationProgress progress = loadProgress(repoPath);
            
            // Filter files
            List filesToTranslate = new ArrayList();
            for (Path file : mdFiles) {
                Path outputPath = getOutputPath(file, repoPath, language.suffix);
                if (Files.exists(outputPath)) {
                    System.out.println("  Skipping (exists): " + repoPath.relativize(file));
                } else if (progress.completed.contains(file.toString())) {
                    System.out.println("  Skipping (completed): " + repoPath.relativize(file));
                } else {
                    filesToTranslate.add(file);
                }
            }
            
            if (filesToTranslate.isEmpty()) {
                System.out.println("\n All files already translated!");
                return;
            }
            
            System.out.println("\n Files to translate: " + filesToTranslate.size());
            System.out.println();
            
            // Confirm
            System.out.print("Translate " + filesToTranslate.size() + " files to " + language.name + "? (y/n): ");
            String confirm = scanner.nextLine().trim().toLowerCase();
            if (!confirm.equals("y")) {
                System.out.println(" Translation cancelled");
                return;
            }
            
            System.out.println();
            System.out.println("=".repeat(70));
            System.out.println("Translating to " + language.name + "...");
            System.out.println("=".repeat(70));
            System.out.println();
            
            // Translate files
            int totalInputChars = 0;
            int totalOutputChars = 0;
            List failedFiles = new ArrayList();
            
            for (int i = 0; i < filesToTranslate.size(); i++) {
                Path inputPath = filesToTranslate.get(i);
                Path relativePath = repoPath.relativize(inputPath);
                Path outputPath = getOutputPath(inputPath, repoPath, language.suffix);
                
                System.out.println("[" + (i + 1) + "/" + filesToTranslate.size() + "] " + relativePath);
                System.out.println("   " + repoPath.relativize(outputPath));
                
                try {
                    int[] chars = translateFile(inputPath, outputPath, language.code);
                    totalInputChars += chars[0];
                    totalOutputChars += chars[1];
                    
                    progress.completed.add(inputPath.toString());
                    saveProgress(repoPath, progress);
                    
                    System.out.println("   Translated (" + chars[0] + "  " + chars[1] + " chars)");
                    System.out.println();
                    
                } catch (Exception e) {
                    System.out.println("   Failed: " + e.getMessage());
                    failedFiles.add(relativePath.toString());
                    progress.failed.add(inputPath.toString());
                    saveProgress(repoPath, progress);
                    System.out.println();
                }
            }
            
            // Summary
            System.out.println("=".repeat(70));
            System.out.println("Translation Complete!");
            System.out.println("=".repeat(70));
            System.out.println(" Translated: " + (filesToTranslate.size() - failedFiles.size()) + " files");
            System.out.println(" Input: " + String.format("%,d", totalInputChars) + " characters");
            System.out.println(" Output: " + String.format("%,d", totalOutputChars) + " characters");
            
            if (!failedFiles.isEmpty()) {
                System.out.println("\n Failed: " + failedFiles.size() + " files");
                for (String file : failedFiles) {
                    System.out.println("  - " + file);
                }
            }
            
            System.out.println("\n Output directory: docs_" + language.suffix + "/");
            System.out.println(" README: README." + language.suffix + ".md");
            System.out.println();
            System.out.println(" Next steps:");
            System.out.println("   1. Review translated files in docs_" + language.suffix + "/");
            System.out.println("   2. git add docs_" + language.suffix + "/ README." + language.suffix + ".md");
            System.out.println("   3. git commit -m 'Add " + language.name + " translation'");
            System.out.println("   4. Create PR");
            
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    private static void printHeader() {
        System.out.println("=".repeat(70));
        System.out.println("Repository Documentation Translation Tool");
        System.out.println("=".repeat(70));
        System.out.println();
    }
    
    private static Language selectLanguage(Scanner scanner) {
        System.out.println("=".repeat(70));
        System.out.println("Select target language:");
        System.out.println("=".repeat(70));
        
        for (Map.Entry entry : LANGUAGES.entrySet()) {
            System.out.printf("  %2s. %s%n", entry.getKey(), entry.getValue().name);
        }
        
        System.out.println();
        while (true) {
            System.out.print("Enter choice (1-20): ");
            String choice = scanner.nextLine().trim();
            if (LANGUAGES.containsKey(choice)) {
                return LANGUAGES.get(choice);
            }
            System.out.println(" Invalid choice. Please enter a number between 1-20.");
        }
    }
    
    private static List findMarkdownFiles(Path repoPath) throws IOException {
        List files = new ArrayList();
        
        // Add README.md
        Path readme = repoPath.resolve("README.md");
        if (Files.exists(readme)) {
            files.add(readme);
        }
        
        // Add all .md files in docs/
        Path docsPath = repoPath.resolve("docs");
        if (Files.exists(docsPath)) {
            Files.walk(docsPath)
                .filter(p -> p.toString().endsWith(".md"))
                .forEach(files::add);
        }
        
        Collections.sort(files);
        return files;
    }
    
    private static Path getOutputPath(Path inputPath, Path repoPath, String langSuffix) {
        String fileName = inputPath.getFileName().toString();
        
        // Handle README.md
        if (fileName.equals("README.md")) {
            return repoPath.resolve("README." + langSuffix + ".md");
        }
        
        // Handle docs/ files
        Path docsPath = repoPath.resolve("docs");
        Path relative = docsPath.relativize(inputPath);
        
        // Change extension: file.md -> file.{lang}.md
        String stem = fileName.substring(0, fileName.length() - 3);
        String newName = stem + "." + langSuffix + ".md";
        
        return repoPath.resolve("docs_" + langSuffix).resolve(relative.getParent()).resolve(newName);
    }
    
    private static int[] translateFile(Path inputPath, Path outputPath, String targetLang) throws IOException {
        // Read input
        String content = Files.readString(inputPath, StandardCharsets.UTF_8);
        int inputChars = content.length();
        
        // Split into chunks
        List chunks = splitContent(content, CHUNK_SIZE);
        
        // Translate chunks
        StringBuilder translated = new StringBuilder();
        for (int i = 0; i < chunks.size(); i++) {
            System.out.print("    Chunk " + (i + 1) + "/" + chunks.size() + "... ");
            String translatedChunk = translateText(chunks.get(i), targetLang);
            translated.append(translatedChunk);
            System.out.println("");
            
            try {
                Thread.sleep(1000); // Rate limiting
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        
        String translatedContent = translated.toString();
        int outputChars = translatedContent.length();
        
        // Create output directory
        Files.createDirectories(outputPath.getParent());
        
        // Write output
        Files.writeString(outputPath, translatedContent, StandardCharsets.UTF_8);
        
        return new int[]{inputChars, outputChars};
    }
    
    private static List splitContent(String content, int chunkSize) {
        List chunks = new ArrayList();
        StringBuilder currentChunk = new StringBuilder();
        boolean inCodeBlock = false;
        
        for (String line : content.split("\n")) {
            if (line.trim().startsWith("```")) {
                inCodeBlock = !inCodeBlock;
            }
            
            if (currentChunk.length() + line.length() > chunkSize && !inCodeBlock && currentChunk.length() > 0) {
                chunks.add(currentChunk.toString());
                currentChunk = new StringBuilder();
            }
            
            currentChunk.append(line).append("\n");
        }
        
        if (currentChunk.length() > 0) {
            chunks.add(currentChunk.toString());
        }
        
        return chunks;
    }
    
    private static String translateText(String text, String targetLang) throws IOException {
        // Use Google Translate API (free, no key required)
        String urlStr = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=" 
            + targetLang + "&dt=t&q=" + URLEncoder.encode(text, StandardCharsets.UTF_8);
        
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("User-Agent", "Mozilla/5.0");
        
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        StringBuilder response = new StringBuilder();
        String line;
        while ((line = in.readLine()) != null) {
            response.append(line);
        }
        in.close();
        
        // Parse JSON response
        JsonArray jsonArray = JsonParser.parseString(response.toString()).getAsJsonArray();
        StringBuilder translated = new StringBuilder();
        
        JsonArray translations = jsonArray.get(0).getAsJsonArray();
        for (int i = 0; i < translations.size(); i++) {
            JsonArray translation = translations.get(i).getAsJsonArray();
            translated.append(translation.get(0).getAsString());
        }
        
        return translated.toString();
    }
    
    private static TranslationProgress loadProgress(Path repoPath) {
        Path progressFile = repoPath.resolve(PROGRESS_FILE);
        if (Files.exists(progressFile)) {
            try {
                String json = Files.readString(progressFile);
                Gson gson = new Gson();
                return gson.fromJson(json, TranslationProgress.class);
            } catch (Exception e) {
                // Ignore errors, return new progress
            }
        }
        return new TranslationProgress();
    }
    
    private static void saveProgress(Path repoPath, TranslationProgress progress) {
        Path progressFile = repoPath.resolve(PROGRESS_FILE);
        try {
            Gson gson = new GsonBuilder().setPrettyPrinting().create();
            String json = gson.toJson(progress);
            Files.writeString(progressFile, json);
        } catch (Exception e) {
            System.err.println("Warning: Could not save progress: " + e.getMessage());
        }
    }
}

Web Proxy Viewer  |  New URL  |  Original Page