Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Java/Openclaw/scripts/docs-i18n/   (KI Agentensystem Version 22©)  Datei vom 26.3.2026 mit Größe 8 kB image not shown  

Quelle  process.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

package main

import (
 "context"
 "fmt"
 "log"
 "os"
 "path/filepath"
 "strings"
 "time"

 "gopkg.in/yaml.v3"
)

func processFile(ctx context.Context, translator docsTranslator, tm *TranslationMemory, docsRoot, filePath, srcLang, tgtLang string) (bool, string, error) {
 absPath, relPath, err := resolveDocsPath(docsRoot, filePath)
 if err != nil {
  return false, "", err
 }

 content, err := os.ReadFile(absPath)
 if err != nil {
  return false, "", err
 }

 frontMatter, body := splitFrontMatter(string(content))
 frontData := map[string]any{}
 if frontMatter != "" {
  if err := yaml.Unmarshal([]byte(frontMatter), &frontData); err != nil {
   return false, "", fmt.Errorf("frontmatter parse failed for %s: %w", relPath, err)
  }
 }

 if err := translateFrontMatter(ctx, translator, tm, frontData, relPath, srcLang, tgtLang); err != nil {
  return false, "", err
 }

 body, err = translateHTMLBlocks(ctx, translator, body, srcLang, tgtLang)
 if err != nil {
  return false, "", err
 }

 segments, err := extractSegments(body, relPath)
 if err != nil {
  return false, "", err
 }

 namespace := cacheNamespace()
 for i := range segments {
  seg := &segments[i]
  seg.CacheKey = cacheKey(namespace, srcLang, tgtLang, seg.SegmentID, seg.TextHash)
  if entry, ok := tm.Get(seg.CacheKey); ok {
   seg.Translated = entry.Translated
   continue
  }
  translated, err := translator.Translate(ctx, seg.Text, srcLang, tgtLang)
  if err != nil {
   return false, "", fmt.Errorf("translate failed (%s): %w", relPath, err)
  }
  seg.Translated = translated
  entry := TMEntry{
   CacheKey:   seg.CacheKey,
   SegmentID:  seg.SegmentID,
   SourcePath: relPath,
   TextHash:   seg.TextHash,
   Text:       seg.Text,
   Translated: translated,
   Provider:   docsPiProvider(),
   Model:      docsPiModel(),
   SrcLang:    srcLang,
   TgtLang:    tgtLang,
   UpdatedAt:  time.Now().UTC().Format(time.RFC3339),
  }
  tm.Put(entry)
 }

 translatedBody := applyTranslations(body, segments)
 updatedFront, err := encodeFrontMatter(frontData, relPath, content)
 if err != nil {
  return false, "", err
 }

 outputPath := filepath.Join(docsRoot, tgtLang, relPath)
 if err := os.MkdirAll(filepath.Dir(outputPath), 0o755); err != nil {
  return false, "", err
 }

 output := updatedFront + translatedBody
 return false, outputPath, os.WriteFile(outputPath, []byte(output), 0o644)
}

func splitFrontMatter(content string) (string, string) {
 if !strings.HasPrefix(content, "---") {
  return "", content
 }
 lines := strings.Split(content, "\n")
 if len(lines) < 2 {
  return "", content
 }
 endIndex := -1
 for i := 1; i < len(lines); i++ {
  if strings.TrimSpace(lines[i]) == "---" {
   endIndex = i
   break
  }
 }
 if endIndex == -1 {
  return "", content
 }
 front := strings.Join(lines[1:endIndex], "\n")
 body := strings.Join(lines[endIndex+1:], "\n")
 if strings.HasPrefix(body, "\n") {
  body = body[1:]
 }
 return front, body
}

func encodeFrontMatter(frontData map[string]any, relPath string, source []byte) (string, error) {
 if frontData == nil {
  frontData = map[string]any{}
 }
 frontData["x-i18n"] = map[string]any{
  "source_path":  relPath,
  "source_hash":  hashBytes(source),
  "provider":     docsPiProvider(),
  "model":        docsPiModel(),
  "workflow":     workflowVersion,
  "generated_at": time.Now().UTC().Format(time.RFC3339),
 }
 encoded, err := yaml.Marshal(frontData)
 if err != nil {
  return "", err
 }
 return fmt.Sprintf("---\n%s---\n\n", string(encoded)), nil
}

func translateFrontMatter(ctx context.Context, translator docsTranslator, tm *TranslationMemory, data map[string]any, relPath, srcLang, tgtLang string) error {
 if len(data) == 0 {
  return nil
 }
 if summary, ok := data["summary"].(string); ok {
  if docsI18nVerboseLogs() {
   log.Printf("docs-i18n: frontmatter start %s field=summary bytes=%d", relPath, len(summary))
  }
  translated, err := translateSnippet(ctx, translator, tm, relPath+":frontmatter:summary", summary, srcLang, tgtLang)
  if err != nil {
   return err
  }
  if docsI18nVerboseLogs() {
   log.Printf("docs-i18n: frontmatter done %s field=summary out_bytes=%d", relPath, len(translated))
  }
  data["summary"] = translated
 }
 if title, ok := data["title"].(string); ok {
  if docsI18nVerboseLogs() {
   log.Printf("docs-i18n: frontmatter start %s field=title bytes=%d", relPath, len(title))
  }
  translated, err := translateSnippet(ctx, translator, tm, relPath+":frontmatter:title", title, srcLang, tgtLang)
  if err != nil {
   return err
  }
  if docsI18nVerboseLogs() {
   log.Printf("docs-i18n: frontmatter done %s field=title out_bytes=%d", relPath, len(translated))
  }
  data["title"] = translated
 }
 if readWhen, ok := data["read_when"].([]any); ok {
  translated := make([]any, 0, len(readWhen))
  for idx, item := range readWhen {
   textValue, ok := item.(string)
   if !ok {
    translated = append(translated, item)
    continue
   }
   if docsI18nVerboseLogs() {
    log.Printf("docs-i18n: frontmatter start %s field=read_when[%d] bytes=%d", relPath, idx, len(textValue))
   }
   value, err := translateSnippet(ctx, translator, tm, fmt.Sprintf("%s:frontmatter:read_when:%d", relPath, idx), textValue, srcLang, tgtLang)
   if err != nil {
    return err
   }
   if docsI18nVerboseLogs() {
    log.Printf("docs-i18n: frontmatter done %s field=read_when[%d] out_bytes=%d", relPath, idx, len(value))
   }
   translated = append(translated, value)
  }
  data["read_when"] = translated
 }
 return nil
}

func docsI18nVerboseLogs() bool {
 value := strings.TrimSpace(os.Getenv("OPENCLAW_DOCS_I18N_VERBOSE_LOGS"))
 if value == "" {
  return false
 }
 switch strings.ToLower(value) {
 case "1", "true", "yes", "on", "debug", "verbose":
  return true
 default:
  return false
 }
}

func translateSnippet(ctx context.Context, translator docsTranslator, tm *TranslationMemory, segmentID, textValue, srcLang, tgtLang string) (string, error) {
 if strings.TrimSpace(textValue) == "" {
  return textValue, nil
 }
 namespace := cacheNamespace()
 textHash := hashText(textValue)
 ck := cacheKey(namespace, srcLang, tgtLang, segmentID, textHash)
 if entry, ok := tm.Get(ck); ok {
  return entry.Translated, nil
 }
 translated, err := translator.Translate(ctx, textValue, srcLang, tgtLang)
 if err != nil {
  return "", err
 }
 shouldCache := true
 if validationErr := validateFrontmatterScalarTranslation(textValue, translated); validationErr != nil {
  log.Printf("docs-i18n: frontmatter fallback %s reason=%v", segmentID, validationErr)
  translated = textValue
  shouldCache = false
 }
 entry := TMEntry{
  CacheKey:   ck,
  SegmentID:  segmentID,
  SourcePath: segmentID,
  TextHash:   textHash,
  Text:       textValue,
  Translated: translated,
  Provider:   docsPiProvider(),
  Model:      docsPiModel(),
  SrcLang:    srcLang,
  TgtLang:    tgtLang,
  UpdatedAt:  time.Now().UTC().Format(time.RFC3339),
 }
 if shouldCache {
  tm.Put(entry)
 }
 return translated, nil
}

func validateFrontmatterScalarTranslation(source, translated string) error {
 trimmed := strings.TrimSpace(translated)
 if trimmed == "" {
  return fmt.Errorf("empty translation")
 }
 lower := strings.ToLower(trimmed)
 if strings.Contains(lower, "<frontmatter>") || strings.Contains(lower, "</frontmatter>") || strings.Contains(lower, "<body>") || strings.Contains(lower, "</body>") {
  return fmt.Errorf("tagged document wrapper detected")
 }
 if strings.Contains(trimmed, "[[[FM_") {
  return fmt.Errorf("frontmatter marker leaked into scalar translation")
 }
 if strings.Contains(trimmed, "\n---\n") || strings.HasPrefix(trimmed, "---\n") {
  return fmt.Errorf("yaml document boundary detected")
 }
 if !strings.Contains(source, "\n") && strings.Count(trimmed, "\n") >= 3 {
  return fmt.Errorf("unexpected multiline expansion")
 }
 sourceLen := len(strings.TrimSpace(source))
 translatedLen := len(trimmed)
 if sourceLen > 0 {
  limit := sourceLen*8 + 256
  if limit < 512 {
   limit = 512
  }
  if translatedLen > limit {
   return fmt.Errorf("unexpected size expansion source=%d translated=%d", sourceLen, translatedLen)
  }
 }
 for _, key := range []string{"title:", "summary:", "read_when:"} {
  if strings.Contains(lower, "\n"+key) || strings.HasPrefix(lower, key) {
   return fmt.Errorf("frontmatter key leaked into scalar translation")
  }
 }
 return nil
}

[Dauer der Verarbeitung: 0.25 Sekunden, vorverarbeitet 2026-04-27]