ing through all files in tags table. Disregard some simple strings which are most probably non-translatable. With prefix argument, restart search at first file." (interactive "P") (require 'etags) ;; Ensure there is no highlighting, in case the search fails. (if po-highlighting (po-dehighlight po-marking-overlay)) (setq po-string-contents nil) ;; Search for a string which might later be marked for translation. (let ((po-current-po-buffer (current-buffer)) (po-current-po-keywords po-keywords)) (pop-to-buffer po-string-buffer) (if (and (not restart) (eq (car tags-loop-operate) 'po-tags-loop-operate)) ;; Continue last po-tags-search. (tags-loop-continue nil) ;; Start or restart po-tags-search all over. (setq tags-loop-scan '(po-tags-loop-scan) tags-loop-operate '(po-tags-loop-operate)) (tags-loop-continue t)) (select-window (get-buffer-window po-current-po-buffer))) (if po-string-contents (let ((window (selected-window)) (buffer po-string-buffer) (start po-string-start) (end po-string-end)) ;; Try to fit the string in the displayed part of its window. (select-window (get-buffer-window buffer)) (goto-char start) (or (pos-visible-in-window-p start) (recenter '(nil))) (if (pos-visible-in-window-p end) (goto-char end) (goto-char end) (recenter -1)) (select-window window) ;; Highlight the string as found. (and po-highlighting (po-highlight po-marking-overlay start end buffer))))) (defun po-tags-loop-scan () "Decide if the current buffer is still interesting for PO mode strings." ;; We have little choice, here. The major mode is needed to dispatch to the ;; proper scanner, so we declare all files as interesting, to force Emacs ;; tags module to revisit files fully. po-tags-loop-operate sets point at ;; end of buffer when it is done with a file. (not (eobp))) (defun po-tags-loop-operate () "Find an acceptable tag in the current buffer, according to mode. Disregard some simple strings which are most probably non-translatable." (po-preset-string-functions) (let ((continue t) data) (while continue (setq data (apply po-find-string-function po-current-po-keywords nil)) (if data ;; Push the string just found into a work buffer for study. (with-temp-buffer (insert (nth 0 data)) (goto-char (point-min)) ;; Accept if at least three letters in a row. (if (re-search-forward "[A-Za-z][A-Za-z][A-Za-z]" nil t) (setq continue nil) ;; Disregard if single letters or no letters at all. (if (re-search-forward "[A-Za-z][A-Za-z]" nil t) ;; Here, we have two letters in a row, but never more. ;; Accept only if more letters than punctuations. (let ((total (buffer-size))) (goto-char (point-min)) (while (re-search-forward "[A-Za-z]+" nil t) (replace-match "" t t)) (if (< (* 2 (buffer-size)) total) (setq continue nil)))))) ;; No string left in this buffer. (setq continue nil))) (if data ;; Save information for marking functions. (let ((buffer (current-buffer))) (save-excursion (set-buffer po-current-po-buffer) (setq po-string-contents (nth 0 data) po-string-buffer buffer po-string-start (nth 1 data) po-string-end (nth 2 data)))) (goto-char (point-max))) ;; If nothing was found, trigger scanning of next file. (not data))) (defun po-mark-found-string (keyword) "Mark last found string in program sources as translatable, using KEYWORD." (if (not po-string-contents) (error (_"No such string"))) (and po-highlighting (po-dehighlight po-marking-overlay)) (let ((contents po-string-contents) (buffer po-string-buffer) (start po-string-start) (end po-string-end) line string) ;; Mark string in program sources. (save-excursion (set-buffer buffer) (setq line (count-lines (point-min) start)) (apply po-mark-string-function start end keyword nil)) ;; Add PO file entry. (let ((buffer-read-only po-read-only)) (goto-char (point-max)) (insert "\n" (format "#: %s:%d\n" (buffer-file-name po-string-buffer) line)) (save-excursion (insert (po-eval-requoted contents "msgid" nil) "msgstr \"\"\n")) (setq po-untranslated-counter (1+ po-untranslated-counter)) (po-update-mode-line-string)) (setq po-string-contents nil))) (defun po-mark-translatable () "Mark last found string in program sources as translatable, using '_'." (interactive) (po-mark-found-string "_")) (defun po-select-mark-and-mark (arg) "Mark last found string in program sources as translatable, ask for keyword, using completion. With prefix argument, just ask the name of a preferred keyword for subsequent commands, also added to possible completions." (interactive "P") (if arg (let ((keyword (list (read-from-minibuffer (_"Keyword: "))))) (setq po-keywords (cons keyword (delete keyword po-keywords)))) (or po-string-contents (error (_"No such string"))) (let* ((default (car (car po-keywords))) (keyword (completing-read (format (_"Mark with keyword? [%s] ") default) po-keywords nil t ))) (if (string-equal keyword "") (setq keyword default)) (po-mark-found-string keyword))))