diff --git a/NEWS b/NEWS
index e6ec5c79..9dcbacac 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,9 @@ TexInfo:
    @documentlanguage (to be manually translated by the humans in the PO file)
    (GitHub's #597 and #598) [Fat-Zer, vindicatorr and mquinson]
 
+TexinfoParser:
+ * New parser based on the Texinfo SWIG interface [Patrice Dumas]
+
 XML:
  * Accept boolean attibutes even if they are the only attribute of their tag
    (GitHub's #608) [mquinson]
diff --git a/lib/Locale/Po4a/Chooser.pm b/lib/Locale/Po4a/Chooser.pm
index 4196b77b..a27707d2 100644
--- a/lib/Locale/Po4a/Chooser.pm
+++ b/lib/Locale/Po4a/Chooser.pm
@@ -18,7 +18,8 @@ use strict;
 use warnings;
 use Locale::Po4a::Common qw(wrap_msg wrap_mod gettext);
 
-my %_mod_lookup = map { lc($_) => $_ } qw( AsciiDoc BibTex KernelHelp LaTeX NewsDebian RubyDoc SimplePod TeX VimHelp );
+my %_mod_lookup =
+  map { lc($_) => $_ } qw( AsciiDoc BibTex KernelHelp LaTeX NewsDebian RubyDoc SimplePod TeX VimHelp TexinfoParser );
 
 sub new {
     my ($module)  = shift;
@@ -28,7 +29,7 @@ sub new {
       unless defined $module;
 
     my $modname;
-    if ( exists($_mod_lookup{$module}) ) {
+    if ( exists( $_mod_lookup{$module} ) ) {
         $modname = $_mod_lookup{$module};
     } elsif ( $module eq 'Rd' ) {
         $modname = 'RubyDoc';
diff --git a/lib/Locale/Po4a/TexinfoParser.pm b/lib/Locale/Po4a/TexinfoParser.pm
new file mode 100644
index 00000000..25233d17
--- /dev/null
+++ b/lib/Locale/Po4a/TexinfoParser.pm
@@ -0,0 +1,962 @@
+#!/usr/bin/perl -w
+
+# Copyright © 2025 Patrice Dumas <pertusus@free.fr>
+#
+# This file is part of po4a.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with po4a; if not, write to the Free Software
+# Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+########################################################################
+#
+# NOTE _convert, _text and _handle_source_marks are originally derived
+# from GNU Texinfo tta/swig/perl/parse_refold.pl, mainly for the
+# handling of source marks.
+
+# TODO
+# * test and handle @verbatiminclude, but may need a discussion
+# * test @include, but probably depends on passing include directories options
+# * use translations to change file names, for example @image file
+#   name?
+# * for brace no_paragraph command, the whole command is translated
+#   it could be each of the arguments.
+# * replace language argument of @documentlanguage
+#   Using $self->{TT}{po_in}->{lang}
+# * add @documentlanguage if there was none
+#   Using $self->{TT}{po_in}->{lang}
+# * do something relevant for @setfilename.  Maybe remove.
+
+# PERL5LIB=../../../lib/ perl ../../../po4a-normalize -f texinfoparser ${file}.texi  -l ${file}.norm -p ${file}.pot
+# PERL5LIB=../../../lib/ perl ../../../po4a-normalize -C -f texinfoparser ${file}.texi -l ${file}.trans -p ${file}.po
+#
+# for file in comments longmenu partialmenus tindex commandsinpara conditionals texifeatures macrovalue linemacro verbatimignore topinifnottex topinifnotdocbook invalidlineecount; do PERL5LIB=../../../lib/ perl ../../../po4a-normalize -f texinfoparser ${file}.texi  -l ${file}.norm -p ${file}.pot ; PERL5LIB=../../../lib/ perl ../../../po4a-normalize -C -f texinfoparser ${file}.texi -l ${file}.trans -p ${file}.po ; done
+
+=encoding UTF-8
+
+=head1 NAME
+
+Locale::Po4a::TexinfoParser - convert Texinfo documents and derivates from/to PO files
+
+=head1 DESCRIPTION
+
+The po4a (PO for anything) project goal is to ease translations (and more
+interestingly, the maintenance of translations) using gettext tools on
+areas where they were not expected like documentation.
+
+Locale::Po4a::TexinfoParser is a module to help the translation of Texinfo documents into
+other [human] languages.
+
+This module uses the GNU Texinfo Parser and Texinfo Tree reader to extract strings and paragraphs to translate.
+
+=begin comment
+
+Only the comments starting with 'TRANSLATORS' are added to the PO files to guide the translators.
+
+=end comment
+
+=head1 STATUS OF THIS MODULE
+
+This module is still beta.
+
+=head1 OPTIONS ACCEPTED BY THIS MODULE
+
+These are this module's particular options:
+
+=over 4
+
+=item no-warn
+
+Do not warn about the current state of this module.
+
+=back
+
+=head1 SEE ALSO
+
+L<Locale::Po4a::Texinfo(3pm)|Locale::Po4a::Texinfo>,
+L<Locale::Po4a::TransTractor(3pm)|Locale::Po4a::TransTractor>,
+L<po4a(7)|po4a.7>
+
+=head1 AUTHORS
+
+ Patrice Dumas <pertusus@free.fr>.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright © 2025 Patrice Dumas <pertusus@free.fr>.
+
+This program is free software; you may redistribute it and/or modify it
+under the terms of GPL v2.0 or later (see the COPYING file).
+
+=cut
+
+package Locale::Po4a::TexinfoParser;
+
+use 5.16.0;
+use strict;
+use warnings;
+
+use parent qw(Locale::Po4a::TransTractor);
+
+use Carp qw(confess);
+
+use Locale::Po4a::Common qw(wrap_mod gettext);
+
+# This is temporary, to be able to find the Texinfo SWIG interface.  Once
+# the release with this interface is common enough, it should not be useful
+# anymore.
+BEGIN {
+    my $home = $ENV{'HOME'};
+    die if ( !defined($home) );
+    my $t2a_builddir = join( '/', ( $home, 'src', 'texinfo', 'tta' ) );
+
+    # for Texinfo.pm
+    unshift @INC, join( '/', ( $t2a_builddir, 'swig', 'perl' ) );
+
+    # for XS
+    unshift @INC, join( '/', ( $t2a_builddir, 'swig', 'perl', '.libs' ) );
+}
+
+use Texinfo;
+
+my $debug = 0;
+
+#$debug = 1;
+
+my %additional_translated_line_commands;
+foreach my $translated_line_cmdname (
+    'xrefname',   'everyheading',   'everyfooting', 'evenheading', 'evenfooting', 'oddheading',
+    'oddfooting', 'shorttitlepage', 'settitle',     'dircategory', 'c',           'comment'
+  )
+{
+    $additional_translated_line_commands{$translated_line_cmdname} = 1;
+}
+
+# TODO add possibility to specify include directories.
+# Other Parser options are much less interesting.  Maybe also file name
+# encoding related such as INPUT_FILE_NAME_ENCODING.  Maybe also, but
+# in very rare cases, clearing/adding expanded formats.
+sub initialize {
+    my $self = shift;
+
+    Texinfo::setup( 0, $Texinfo::txi_interpreter_use_no_interpreter );
+
+    # Set in TeX.pm for the original Texinfo parser
+    #$self->{options}{'no-warn'}         = 0;
+}
+
+=item B<read>
+
+Overloads Transtractor's read().
+
+=cut
+
+sub read ($$$$) {
+    my ( $self, $filename, $refname, $charset ) = @_;
+
+    push @{ $self->{file_charsets}{infile} }, [ $filename, $charset ];
+}
+
+sub parse {
+    my $self = shift;
+
+    # FIXME gets added to stderr for tests, which then fail
+    #print STDERR "The TexinfoParser module of po4a is not ready for production use.\n"
+    #  . "(use -o no-warn to remove this message)\n"
+    #  unless $self->{options}{'no-warn'};
+    map { $self->parse_file($_) } @{ $self->{file_charsets}{infile} };
+}
+
+sub _output_txi_error_messages {
+    my $error_messages_list = shift;
+
+    my $msg_number = Texinfo::messages_list_messages_number($error_messages_list);
+    if ( $msg_number > 0 ) {
+        for ( my $i = 0 ; $i < $msg_number ; $i++ ) {
+            my $error_msg     = Texinfo::messages_list_message_by_index( $error_messages_list, $i );
+            my $formatted_msg = $error_msg->swig_formatted_get();
+            if ( $error_msg->swig_continuation_get() ) {
+                warn($formatted_msg);
+            } else {
+                chomp $formatted_msg;
+                warn( wrap_mod( "po4a::texinfo", $formatted_msg ) );
+            }
+        }
+    }
+}
+
+# SWIG always uses sv_setpvn returning bytes and C encodes in UTF-8, so we
+# convert to Perl characters by decoding from UTF-8
+sub _decode($) {
+    my $text = shift;
+    return Encode::decode( 'UTF-8', $text );
+}
+
+sub _current_smark($) {
+    my $current_smark = shift;
+
+    return defined($current_smark) ? "$current_smark->[0]:$current_smark->[1]" : '-';
+}
+
+sub _text($$$;$) {
+    my ( $text, $from, $type, $to ) = @_;
+
+    my $result = '';
+
+    $from = 0 if ( !defined($from) );
+
+    if ( $type eq 'bracketed_linemacro_arg' ) {
+
+        # recreate the text the source marks are relative too
+        $text = '{' . $text . '}';
+    }
+
+    my $length;
+    if ( defined($to) ) {
+        $length = $to - $from;
+    }
+
+    if ( defined($length) ) {
+        $result .= substr( $text, $from, $length );
+    } else {
+        $result .= substr( $text, $from );
+    }
+    return $result;
+}
+
+sub _translation_begin_info($$$$) {
+    my $inputs           = shift;
+    my $wrap             = shift;
+    my $translation_type = shift;
+    my $result           = shift;
+
+    my $to_translate = '';
+    my $translation_info =
+      [ \$to_translate, "$inputs->[-1]->[0]:$inputs->[-1]->[1]", $wrap, $translation_type, $result ];
+    return ( $translation_info, $translation_info->[0] );
+}
+
+sub _translation_end($$$) {
+    my $self             = shift;
+    my $translation_info = shift;
+    my $result           = shift;
+
+    my ( $to_translate_reference, $ref, $wrap, $translation_type, $previous_result ) = @$translation_info;
+    my $translated;
+    if ( $to_translate_reference ne $result ) {
+        warn "BUG: $translation_type $ref text $to_translate_reference != result $result\n";
+    }
+    if ($debug) {
+        print STDERR "TT: $ref, $translation_type, $wrap!!$$to_translate_reference!!\n";
+    }
+    my $trailing_eol;
+    if ( $$to_translate_reference =~ /\S/ ) {
+
+        # always remove trailing end of line from translated strings
+        if ( $$to_translate_reference =~ s/(\n)$// ) {
+            $trailing_eol = $1;
+        }
+        $translated = $self->translate( $$to_translate_reference, $ref, $translation_type, 'wrap' => $wrap );
+    } else {
+        $translated = $$to_translate_reference;
+    }
+    $result = $previous_result;
+    $$result .= $translated;
+    if ( defined($trailing_eol) ) {
+        $$result .= $trailing_eol;
+    }
+    return $result;
+}
+
+sub _handle_source_marks($$$$$$$$) {
+    my ( $self, $result, $element, $document, $type, $inputs, $translation_info, $current_smark ) = @_;
+
+    my $last_position;
+    my $smark_e_text;
+    my $source_marks_nr = Texinfo::element_source_marks_number($element);
+    if ($source_marks_nr) {
+        if ($debug) {
+            print STDERR "_SOURCEMARKS ($source_marks_nr)\n";
+        }
+        for ( my $i = 0 ; $i < $source_marks_nr ; $i++ ) {
+            my $source_mark         = Texinfo::element_get_source_mark( $element, $i );
+            my $source_mark_counter = $source_mark->swig_counter_get();
+            my $source_mark_type    = $source_mark->swig_type_get();
+
+            if ($current_smark) {
+                if (    $source_mark_counter == $current_smark->[1]
+                    and $current_smark->[0] eq $source_mark_type )
+                {
+                    $last_position = $source_mark->swig_position_get();
+                    if ($debug) {
+                        print STDERR "END_SMARK($i): $source_mark_type;" . "c:$source_mark_counter;p:$last_position\n";
+                    }
+                    $current_smark = undef;
+                }
+            }
+
+            my $source_mark_status = $source_mark->swig_status_get();
+
+            my $source_mark_position = $source_mark->swig_position_get();
+            if ( defined($source_mark_position) and $source_mark_position > 0 ) {
+                if ( !$current_smark ) {
+
+                    # source_mark_position > 0 only in text elements
+                    my $text        = _decode( Texinfo::element_text($element) );
+                    my $text_result = _text( $text, $last_position, $type, $source_mark_position );
+                    if ($debug) {
+                        print STDERR "TEXT_SMARK($i) "
+                          . ( defined($last_position) ? $last_position : '-' )
+                          . ":$source_mark_position"
+                          . " '$text_result'\n";
+
+                        #."\n";
+                    }
+                    $$result .= $text_result;
+
+                    # there may be multiple end of line in macro_call_arg_text
+                    my $count = ( $text_result =~ tr/\n// );
+                    $inputs->[-1]->[1] += $count;
+                }
+            }
+            $last_position = $source_mark_position;
+
+            # value expansion has both a line and an element, the line
+            # is the flag name, what we are interested in is the element
+            my $source_mark_element = $source_mark->swig_element_get();
+            if ( defined($source_mark_element) ) {
+                if ($debug) {
+                    print STDERR "_E_SMARK($i): "
+
+                      #.Texinfo::tree_print_details($source_mark_element)."\n";
+                      . "\n";
+                }
+
+                my $translation_type;
+                if ( $source_mark_type == $Texinfo::SM_type_ignored_conditional_block
+                    and !defined($translation_info) )
+                {
+                    # translate @if* ignored block
+                    $translation_type = '@' . Texinfo::element_cmdname($source_mark_element);
+                    ( $translation_info, $result ) = _translation_begin_info( $inputs, 0, $translation_type, $result );
+                }
+                ( $result, $current_smark ) =
+                  _convert( $self, $result, $source_mark_element, $document, $inputs, $translation_info,
+                    $current_smark );
+                if ( defined($translation_type) ) {
+                    $result           = _translation_end( $self, $translation_info, $result );
+                    $translation_info = undef;
+                }
+            } elsif ( !$current_smark ) {
+                if ( $source_mark_type == $Texinfo::SM_type_delcomment ) {
+                    $$result .= "\x{7F}";
+                } elsif ( $source_mark_type == $Texinfo::SM_type_macro_arg_escape_backslash ) {
+                    $$result .= '\\';
+                }
+                my $source_mark_line = _decode( $source_mark->swig_line_get() );
+                my $translation_type;
+                if ( defined($source_mark_line) ) {
+                    if ( $source_mark_type == $Texinfo::SM_type_delcomment
+                        and !defined($translation_info) )
+                    {
+                        # translate DEL comment
+                        $translation_type = 'DEL comment';
+                        ( $translation_info, $result ) =
+                          _translation_begin_info( $inputs, 0, $translation_type, $result );
+                    }
+                    $$result .= $source_mark_line;
+                    $inputs->[-1]->[1] += 1 if ( $source_mark_line =~ /\n/ );
+                    if ( defined($translation_type) ) {
+                        $result           = _translation_end( $self, $translation_info, $result );
+                        $translation_info = undef;
+                    }
+                } elsif ( $source_mark_type == $Texinfo::SM_type_defline_continuation ) {
+                    $$result .= "@\n";
+                    $inputs->[-1]->[1] += 1;
+                }
+            }
+            if ( $source_mark_type eq $Texinfo::SM_type_include ) {
+                if ( $source_mark_status eq $Texinfo::SM_status_start ) {
+                    my $file_name = Texinfo::element_attribute_string( $source_mark_element, 'text_arg' );
+                    if ($debug) {
+                        print STDERR "INCLUDE($i) '$file_name' "
+                          . "c:$source_mark_counter;s_m:"
+                          . _current_smark($current_smark) . "\n";
+                    }
+                    my $result_text = '';
+                    $result = \$result_text;
+                    push @$inputs, [ $file_name, 1, $result, $source_mark_counter, $current_smark ];
+                    $current_smark = undef;
+                } elsif ( $source_mark_status eq $Texinfo::SM_status_end ) {
+                    my $previous_input = pop @$inputs;
+                    if ($debug) {
+                        print STDERR "END_INCLUDE($i) c:$source_mark_counter"
+                          . "|$previous_input->[3];s_m:"
+                          . _current_smark( $inputs->[-1]->[4] ) . " \n";
+                    }
+
+                    #_write_output($previous_input);
+                    $current_smark = $previous_input->[4];
+                    $result        = $inputs->[-1]->[2];
+                }
+            } elsif ( !$current_smark ) {
+                if (
+                    $source_mark_status eq $Texinfo::SM_status_start
+
+                    # expanded conditional has a start and an end, but the
+                    # tree within is the expanded tree and should not be skipped
+                    and $source_mark_type != $Texinfo::SM_type_expanded_conditional_command
+                  )
+                {
+                    if ($debug) {
+                        print STDERR "START_SMARK($i): $source_mark_type;" . "c:$source_mark_counter\n";
+                    }
+                    $current_smark = [ $source_mark_type, $source_mark_counter ];
+                }
+            }
+        }
+        if ($debug) {
+            print STDERR "_OUTSMARKS [p:"
+              . ( defined($last_position) ? $last_position : 0 ) . "] "
+              . _current_smark($current_smark) . "\n";
+        }
+    }
+    return $result, $last_position, $current_smark;
+}
+
+# $self->translate($string, $ref, $type)
+# type is line paragraph, @node, can also hold argument number
+# $ref should be $file:$line_nr
+# $self->pushline($text);
+
+sub _arg_parent_element($) {
+    my $element = shift;
+
+    my $parent = Texinfo::element_parent($element);
+    return undef if ( !defined($parent) );
+    my $parent_type = Texinfo::element_type($parent);
+    if ( defined($parent_type) and $parent_type eq 'arguments_line' ) {
+        $parent = Texinfo::element_parent($parent);
+        return undef if ( !defined($parent) );
+    }
+    my $cmdname = Texinfo::element_cmdname($parent);
+    return undef if ( !defined($cmdname) );
+    return $parent;
+}
+
+sub _translated_line_arg($) {
+    my $element = shift;
+
+    my $parent = _arg_parent_element($element);
+    return undef if ( !defined($parent) );
+    my $cmdname = Texinfo::element_cmdname($parent);
+    if (   Texinfo::element_command_is_formatted_line($parent)
+        or Texinfo::element_command_is_index_entry_command($parent)
+        or exists( $additional_translated_line_commands{$cmdname} ) )
+    {
+        return $cmdname;
+    }
+    return undef;
+}
+
+sub _translated_block_line_arg($) {
+    my $element = shift;
+
+    my $parent = _arg_parent_element($element);
+    return undef if ( !defined($parent) );
+    my $cmdname = Texinfo::element_cmdname($parent);
+
+    # @example is not there, as it is likely that @example arguments do
+    # not need to be translated.
+    if (   $cmdname eq 'quotation'
+        or $cmdname eq 'smallquotation'
+        or $cmdname eq 'float'
+        or $cmdname eq 'cartouche' )
+    {
+        return $cmdname;
+    } elsif ( $cmdname eq 'multitable' ) {
+        my $elements_nr = Texinfo::element_children_number($element);
+        if ( $elements_nr > 0 ) {
+            my $first_element     = Texinfo::element_get_child( $element, 0 );
+            my $first_elt_cmdname = Texinfo::element_cmdname($first_element);
+            if ( defined($first_elt_cmdname)
+                and $first_elt_cmdname eq 'columnfractions' )
+            {
+                return undef;
+            }
+        }
+        return $cmdname;
+    } elsif ( $cmdname eq 'itemize' ) {
+
+        # text, not command, as itemize argument
+        my $argument_command = Texinfo::block_line_argument_command($element);
+        if ( !defined($argument_command) ) {
+            return $cmdname;
+        }
+    }
+    return undef;
+}
+
+sub _translated_def_arg($) {
+    my $element = shift;
+
+    my $parent = Texinfo::element_parent($element);
+    return undef if ( !defined($parent) );
+
+    my $def_cmdname = Texinfo::element_attribute_string( $parent, 'original_def_cmdname' );
+    return $def_cmdname;
+}
+
+sub _print_translation_stack($) {
+    my $translation_stack = shift;
+
+    my @translation_on_stacks;
+    foreach my $translation_on_stack (@$translation_stack) {
+        if ( !defined($translation_on_stack) ) {
+            push @translation_on_stacks, '-';
+        } else {
+
+            #push @translation_on_stacks, '('.join(',', @$translation_on_stack).')';
+            push @translation_on_stacks, $translation_on_stack;
+        }
+    }
+    return join( '', @translation_on_stacks );
+}
+
+sub _convert($$$$$;$$);
+
+sub _convert($$$$$;$$) {
+    my ( $self, $result, $tree, $document, $inputs, $translation_info, $current_smark ) = @_;
+
+    if ( ref($inputs) ne 'ARRAY' or ref( $inputs->[-1] ) ne 'ARRAY' ) {
+        confess();
+    }
+    if ($debug) {
+        print STDERR "_CONVERT: " . _current_smark($current_smark) . "\n";
+    }
+    my $reader = Texinfo::new_reader( $tree, $document );
+
+    my $args_stack         = [];
+    my $translations_stack = [];
+    my $translation_state;
+
+    while (1) {
+        my $next_token = Texinfo::reader_read($reader);
+        last if ( !defined($next_token) );
+
+        my $element  = $next_token->swig_element_get();
+        my $category = $next_token->swig_category_get();
+
+        my $type = Texinfo::element_type($element);
+        $type = '' if ( !defined($type) );
+
+        if ($debug) {
+            print STDERR "R !$result! ["
+              . join( '|', @$args_stack )
+              . "] $category "
+              . _current_smark($current_smark) . ' '
+              . _print_translation_stack($translations_stack) . "\n" . ' '
+              . Texinfo::element_print_details($element) . "\n";
+        }
+
+        if (   $category == $Texinfo::TXI_READ_TEXT
+            or $category == $Texinfo::TXI_READ_IGNORABLE_TEXT )
+        {
+            my ( $last_position, $smark_result );
+            ( $result, $last_position, $current_smark ) =
+              _handle_source_marks( $self, $result, $element, $document, $type, $inputs, $translation_info,
+                $current_smark );
+            if ( !defined($current_smark) ) {
+                if ( $type eq 'spaces' ) {
+                    my ( $inserted, $status ) = Texinfo::element_attribute_integer( $element, 'inserted' );
+                    next if ($inserted);
+                }
+                my $text        = _decode( Texinfo::element_text($element) );
+                my $text_result = _text( $text, $last_position, $type );
+                $$result .= $text_result;
+
+                # there may be multiple end of line in macro_call_arg_text
+                my $count = ( $text_result =~ tr/\n// );
+                $inputs->[-1]->[1] += $count;
+            }
+            next;
+        }
+
+        my $translation_on_stack;
+        my $cmdname = Texinfo::element_cmdname($element);
+
+        if ( defined($cmdname) ) {
+
+            # trnalsted commands
+            if ( $category == $Texinfo::TXI_READ_ELEMENT_START ) {
+                if ( !defined($translation_info) ) {
+                    if ( $cmdname eq 'documentlanguage' ) {
+
+                        # In tests, this is never set.
+                        my $translation_language;
+                        if ( defined( $self->{TT}{po_in}->{lang} ) ) {
+                            $translation_language = $self->{TT}{po_in}->{lang};
+                        } else {
+                            $translation_language = '-';
+                        }
+
+                        # TODO normalize and modify argument
+                        if ($debug) {
+                            print STDERR "LANGUAGE: $translation_language\n";
+                        }
+                    }
+                    if (
+                           $cmdname eq 'macro'
+                        or $cmdname eq 'rmacro'
+                        or $cmdname eq 'linemacro'
+                        or $cmdname eq 'set'
+                        or $cmdname eq 'ignore'
+                        or $cmdname eq 'verbatim'
+                        or $cmdname eq 'displaymath'
+
+                        # brace @-commands that happen outside of paragraphs.
+                        # Need to do a check in commands data file that the
+                        # arguments are to be translated, or special-case as done
+                        # for @image
+                        or (    Texinfo::element_command_is_brace($element)
+                            and Texinfo::element_command_is_no_paragraph($element)
+                            and $cmdname ne 'image' )
+                      )
+                    {
+                        ( $translation_info, $result ) = _translation_begin_info( $inputs, 0, '@' . $cmdname, $result );
+                        $translation_on_stack = 'C';
+                    }
+
+                    # TODO translate @macro, @ignore, @set
+                    # and probably others
+                }
+                push @$translations_stack, $translation_on_stack;
+            }
+            if ( $category != $Texinfo::TXI_READ_ELEMENT_END ) {
+                if ( !defined($current_smark) ) {
+                    my $alias_of = Texinfo::element_attribute_string( $element, 'alias_of' );
+                    $$result .= '@';
+                    if ( defined($alias_of) ) {
+                        $$result .= $alias_of;
+                    } else {
+                        $$result .= $cmdname;
+                        $inputs->[-1]->[1] += 1 if ( $cmdname eq "\n" );
+                    }
+                }
+
+                my $spaces_cmd_before_arg =
+                  Texinfo::element_attribute_element( $element, 'spaces_after_cmd_before_arg' );
+                if ( defined($spaces_cmd_before_arg) ) {
+                    ( $result, $current_smark ) = _convert( $self, $result, $spaces_cmd_before_arg, $document,
+                        $inputs, $translation_info, $current_smark );
+                }
+            }
+
+            if ( $category == $Texinfo::TXI_READ_ELEMENT_START ) {
+                if (   Texinfo::element_command_is_brace($element)
+                    or $type eq 'definfoenclose_command'
+                    or $type eq 'macro_call'
+                    or $type eq 'rmacro_call' )
+                {
+                    if ( !defined($current_smark) ) {
+                        if ( Texinfo::element_type( Texinfo::element_get_child( $element, 0 ) ) ne 'following_arg' ) {
+                            $$result .= '{';
+                        }
+                        if ( $cmdname eq 'verb' ) {
+                            my $verb_delimiter = _decode( Texinfo::element_attribute_string( $element, 'delimiter' ) );
+                            $$result .= $verb_delimiter;
+                            $inputs->[-1]->[1] += 1 if ( $verb_delimiter eq "\n" );
+                        }
+                    }
+                    push @$args_stack, 0;
+                } elsif ( !Texinfo::element_command_is_nobrace($element) ) {
+                    push @$args_stack, 0;
+                }
+
+            } elsif ( $category == $Texinfo::TXI_READ_ELEMENT_END ) {
+                if (   Texinfo::element_command_is_brace($element) or $type eq 'definfoenclose_command',
+                    or $type eq 'macro_call'
+                    or $type eq 'rmacro_call' )
+                {
+                    if ( !defined($current_smark) ) {
+                        if ( $cmdname eq 'verb' ) {
+                            my $verb_delimiter = _decode( Texinfo::element_attribute_string( $element, 'delimiter' ) );
+                            $$result .= $verb_delimiter;
+                            $inputs->[-1]->[1] += 1 if ( $verb_delimiter eq "\n" );
+                        }
+                        if ( Texinfo::element_type( Texinfo::element_get_child( $element, 0 ) ) ne 'following_arg' ) {
+                            $$result .= '}';
+                        }
+                    }
+                }
+            }
+        } else {    # !defined($cmdname)
+            if ( $category == $Texinfo::TXI_READ_ELEMENT_START ) {
+                my ( $inserted, $status ) = Texinfo::element_attribute_integer( $element, 'inserted' );
+                if ($inserted) {
+                    Texinfo::reader_skip_children( $reader, $element );
+                    next;
+                }
+            }
+            if (   $category == $Texinfo::TXI_READ_ELEMENT_START
+                or $category == $Texinfo::TXI_READ_EMPTY )
+            {
+                if ( !defined($current_smark) ) {
+                    if ( $type eq 'bracketed_arg' ) {
+                        $$result .= '{';
+                    }
+                }
+                if (   $type eq 'brace_arg'
+                    or $type eq 'elided_brace_command_arg'
+                    or $type eq 'line_arg'
+                    or $type eq 'block_line_arg' )
+                {
+                    $args_stack->[-1]++;
+                    if ( !defined($current_smark) ) {
+                        if ( $args_stack->[-1] > 1 ) {
+                            $$result .= ',';
+                        }
+                    }
+                }
+            }
+        }
+        if (   $category == $Texinfo::TXI_READ_ELEMENT_START
+            or $category == $Texinfo::TXI_READ_EMPTY )
+        {
+
+            my $spaces_before_argument = Texinfo::element_attribute_element( $element, 'spaces_before_argument' );
+            if ( defined($spaces_before_argument) ) {
+                ( $result, $current_smark ) = _convert( $self, $result, $spaces_before_argument, $document,
+                    $inputs, $translation_info, $current_smark );
+            }
+            my $source_info = Texinfo::element_source_info($element);
+            if ( defined($source_info) ) {
+
+                # TODO check if file name is synced too?
+                my $line_nr = $source_info->swig_line_nr_get();
+                if ( $line_nr != 0 and $line_nr != $inputs->[-1]->[1] ) {
+
+                    # TODO only show for tests?
+                    if ($debug) {
+                        warn "WARNING: line nr out of sync $line_nr != $inputs->[-1]->[1]\n";
+                    }
+                    $inputs->[-1]->[1] = $line_nr;
+                }
+            }
+        }
+
+        # Setup element translation_info for a translation span on
+        # command arguments, preformatted, paragraph and menu entry.
+        if ( $category == $Texinfo::TXI_READ_ELEMENT_START
+            and !defined($cmdname) )
+        {
+            # NOTE it could have been possible to do nothing if
+            # !defined($current_smark).  This is not needed, however, since the
+            # text is empty anyway and not translated because it is empty.
+            #
+            # Never nest translations, if there is already text to be translated
+            # being gathered, the tree that would have been translated on its
+            # own will instead be translated as part of the ongoing parent
+            # tree element translation.
+            if ( !defined($translation_info) ) {
+                my $wrap;
+                my $parent_cmdname;
+                if ( $type eq 'paragraph' ) {
+
+                    # FIXME never wrap to keep the structure in paragraph as
+                    # end of line delimitate comments and index entries, and also
+                    # index entries should remain at line beginning.
+                    #$wrap = 1;
+                    $wrap = 0;
+                } elsif ( $type eq 'preformatted' or $type eq 'menu_entry' ) {
+                    $wrap = 0;
+                } elsif ( $type eq 'block_line_arg'
+                    and _translated_block_line_arg($element) )
+                {
+                    $parent_cmdname = _translated_block_line_arg($element);
+                    $wrap           = 0;
+                } elsif ( $type eq 'line_arg'
+                    and _translated_line_arg($element) )
+                {
+                    $parent_cmdname = _translated_line_arg($element);
+                    $wrap           = 0;
+                } elsif ( ( $type eq 'block_line_arg' or $type eq 'line_arg' )
+                    and defined( _translated_def_arg($element) ) )
+                {
+                    $parent_cmdname = _translated_def_arg($element);
+                    $wrap           = 0;
+                } elsif ( $type eq 'brace_arg'
+                    and $args_stack->[-1] == 4
+                    and _arg_parent_element($element)
+                    and Texinfo::element_cmdname( _arg_parent_element($element) ) eq 'image' )
+                {
+                    $parent_cmdname = 'image';
+
+                    # not sure.  comment could be possible even though it is
+                    # not valid Texinfo
+                    $wrap = 0;
+                }
+                if ( defined($wrap) ) {
+                    my $translation_type = $type;
+
+                    if ( defined($parent_cmdname) ) {
+                        $translation_type .= " $args_stack->[-1] in \@$parent_cmdname";
+                    }
+
+                    ( $translation_info, $result ) =
+                      _translation_begin_info( $inputs, $wrap, $translation_type, $result );
+                    $translation_on_stack = 'A';
+                    if ($debug) {
+                        print STDERR "PUSH T $result: " . '(' . join( ',', @$translation_info ) . ')' . "\n";
+                    }
+                }
+            }
+            push @$translations_stack, $translation_on_stack;
+        }
+        if (   $category == $Texinfo::TXI_READ_EMPTY
+            or $category == $Texinfo::TXI_READ_ELEMENT_END )
+        {
+            my $spaces_after_argument = Texinfo::element_attribute_element( $element, 'spaces_after_argument' );
+            if ( defined($spaces_after_argument) ) {
+                ( $result, $current_smark ) = _convert( $self, $result, $spaces_after_argument, $document,
+                    $inputs, $translation_info, $current_smark );
+            }
+
+            if ( $type eq 'line_arg' or $type eq 'block_line_arg' ) {
+                my $comment_e = Texinfo::element_attribute_element( $element, 'comment_at_end' );
+                if ($comment_e) {
+                    my $comment;
+                    ( $result, $current_smark ) =
+                      _convert( $self, $result, $comment_e, $document, $inputs, $translation_info, $current_smark );
+                }
+            }
+
+            if ( !defined($current_smark) ) {
+                if ( $type eq 'bracketed_arg' ) {
+                    $$result .= '}';
+                }
+            }
+        }
+
+        if ( $category == $Texinfo::TXI_READ_ELEMENT_END ) {
+            if ( defined($cmdname)
+                and !Texinfo::element_command_is_nobrace($element) )
+            {
+                pop @$args_stack;
+            }
+        }
+
+        if ( $category == $Texinfo::TXI_READ_ELEMENT_END ) {
+            my $translation_on_stack = pop @$translations_stack;
+            if ( defined($translation_on_stack) ) {
+                $result           = _translation_end( $self, $translation_info, $result );
+                $translation_info = undef;
+            }
+        }
+
+        if (   $category == $Texinfo::TXI_READ_EMPTY
+            or $category == $Texinfo::TXI_READ_ELEMENT_END )
+        {
+            my ( $last_position, $smark_result );
+            ( $result, $last_position, $current_smark ) =
+              _handle_source_marks( $self, $result, $element, $document, $type, $inputs, $translation_info,
+                $current_smark );
+        }
+    }
+
+    if ($debug) {
+        print STDERR "_END " . _current_smark($current_smark) . "\n";
+
+        #print STDERR "RESULT: '$$result'\n";
+    }
+    return ( $result, $current_smark );
+}
+
+sub parse_file {
+    my $self             = shift;
+    my $file_and_charset = shift;
+    my ( $filename, $charset ) = @$file_and_charset;
+
+    my $parser = Texinfo::parser;
+
+    Texinfo::parser_conf_clear_expanded_formats($parser);
+
+    # Only tex is not there
+    foreach my $format ( 'info', 'plaintext', 'html', 'latex', 'docbook', 'xml' ) {
+        Texinfo::parser_conf_add_expanded_format( $parser, $format );
+    }
+    my ( $document, $status ) = Texinfo::parse_file( $parser, $filename );
+
+    my ( $parser_error_msgs, $error_nr ) = Texinfo::get_parser_error_messages($document);
+    _output_txi_error_messages($parser_error_msgs);
+    if ($status) {
+        exit 1;
+    }
+
+    # check that the charset is the same as the Texinfo @documentencoding
+    # FIXME is it really useful?
+    if ( defined($charset) ) {
+        my $global_info = Texinfo::document_global_information($document);
+
+        my $encoding = $global_info->swig_input_encoding_name_get();
+
+        # not actually possible, encoding is set to in the default case.
+        $encoding = 'UTF-8' if ( !defined($encoding) );
+
+        # To support old manuals in which US-ASCII can be specified although
+        # the encoding corresponds to any 8bit encoding compatible with ISO-8859-1,
+        # we also consider US-ASCII as ISO-8859-1 to avoid errors for characters in
+        # ISO-8859-1 but not in US-ASCII.
+        my @encodings = ($encoding);
+        if ( lc($encoding) eq 'us-ascii' ) {
+            push @encodings, 'iso-8859-1';
+        }
+
+        my $encoding_found;
+        foreach my $input_encoding (@encodings) {
+            if ( lc($charset) eq lc($input_encoding) ) {
+                $encoding_found = 1;
+                last;
+            }
+        }
+        if ( !$encoding_found ) {
+            wrap_mod( "po4a::texinfo", gettext('Document encoding %s differs from encoding %s'),
+                $encodings[0], $charset );
+        }
+    }
+
+    my $tree = Texinfo::document_tree($document);
+
+    my $current_smark;
+    my $inputs      = [ [ $filename, 1, undef, -1, undef ] ];
+    my $elements_nr = Texinfo::element_children_number($tree);
+
+    # NOTE this could possibly fail if there are macro expansions across
+    # top-level elements boundaries, but also @if*.  @if* have been
+    # tested to be ok.
+    for ( my $i = 0 ; $i < $elements_nr ; $i++ ) {
+        my $result_text = '';
+        $inputs->[0]->[2] = \$result_text;
+        my $result;
+        my $element = Texinfo::element_get_child( $tree, $i );
+        ( $result, $current_smark ) = _convert( $self, $inputs->[0]->[2], $element, $document, $inputs );
+        $self->pushline($$result);
+    }
+
+    if ( defined($current_smark) ) {
+        warn "REMARK: Source mark not closed\n";
+    }
+}
+
+1;
diff --git a/t/fmt-texinfoparser.t b/t/fmt-texinfoparser.t
new file mode 100644
index 00000000..5705765b
--- /dev/null
+++ b/t/fmt-texinfoparser.t
@@ -0,0 +1,28 @@
+# Texinfo based on Parser module tester.
+
+#########################
+
+use strict;
+use warnings;
+
+use lib q(t);
+use Testhelper;
+
+my @tests;
+
+for my $test (
+    qw(longmenu partialmenus comments tindex commandsinpara
+    conditionals texifeatures macrovalue linemacro verbatimignore
+    topinifnottex topinifnotdocbook invalidlineecount)
+  )
+{
+    push @tests,
+      {
+        'format'  => 'texinfoparser',
+        'input'   => "fmt/texinfoparser/$test.texi",
+        'options' => '-o no-warn',
+      };
+}
+
+run_all_tests(@tests);
+0;
diff --git a/t/fmt/texinfoparser/commandsinpara.norm b/t/fmt/texinfoparser/commandsinpara.norm
new file mode 100644
index 00000000..62369c04
--- /dev/null
+++ b/t/fmt/texinfoparser/commandsinpara.norm
@@ -0,0 +1,9 @@
+@node Top
+@top top
+ 
+A paragraph begins, and
+@comment in pcomm
+it continues between @comment a comment in line
+@cindex i entry
+commands.
+
diff --git a/t/fmt/texinfoparser/commandsinpara.po b/t/fmt/texinfoparser/commandsinpara.po
new file mode 100644
index 00000000..85cdbfe7
--- /dev/null
+++ b/t/fmt/texinfoparser/commandsinpara.po
@@ -0,0 +1,45 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @node
+#: commandsinpara.texi:1
+#, no-wrap
+msgid "Top"
+msgstr "TOP"
+
+#. type: line_arg 1 in @top
+#: commandsinpara.texi:2
+#, no-wrap
+msgid "top"
+msgstr "TOP"
+
+#. type: paragraph
+#: commandsinpara.texi:4
+#, no-wrap
+msgid ""
+"A paragraph begins, and\n"
+"@comment in pcomm\n"
+"it continues between @comment a comment in line\n"
+"@cindex i entry\n"
+"commands."
+msgstr ""
+"A PARAGRAPH BEGINS, AND\n"
+"@COMMENT IN PCOMM\n"
+"IT CONTINUES BETWEEN @COMMENT A COMMENT IN LINE\n"
+"@CINDEX I ENTRY\n"
+"COMMANDS."
diff --git a/t/fmt/texinfoparser/commandsinpara.pot b/t/fmt/texinfoparser/commandsinpara.pot
new file mode 100644
index 00000000..6bdcf22e
--- /dev/null
+++ b/t/fmt/texinfoparser/commandsinpara.pot
@@ -0,0 +1,40 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @node
+#: commandsinpara.texi:1
+#, no-wrap
+msgid "Top"
+msgstr ""
+
+#. type: line_arg 1 in @top
+#: commandsinpara.texi:2
+#, no-wrap
+msgid "top"
+msgstr ""
+
+#. type: paragraph
+#: commandsinpara.texi:4
+#, no-wrap
+msgid ""
+"A paragraph begins, and\n"
+"@comment in pcomm\n"
+"it continues between @comment a comment in line\n"
+"@cindex i entry\n"
+"commands."
+msgstr ""
diff --git a/t/fmt/texinfoparser/commandsinpara.texi b/t/fmt/texinfoparser/commandsinpara.texi
new file mode 100644
index 00000000..62369c04
--- /dev/null
+++ b/t/fmt/texinfoparser/commandsinpara.texi
@@ -0,0 +1,9 @@
+@node Top
+@top top
+ 
+A paragraph begins, and
+@comment in pcomm
+it continues between @comment a comment in line
+@cindex i entry
+commands.
+
diff --git a/t/fmt/texinfoparser/commandsinpara.trans b/t/fmt/texinfoparser/commandsinpara.trans
new file mode 100644
index 00000000..7f11efef
--- /dev/null
+++ b/t/fmt/texinfoparser/commandsinpara.trans
@@ -0,0 +1,9 @@
+@node TOP
+@top TOP
+ 
+A PARAGRAPH BEGINS, AND
+@COMMENT IN PCOMM
+IT CONTINUES BETWEEN @COMMENT A COMMENT IN LINE
+@CINDEX I ENTRY
+COMMANDS.
+
diff --git a/t/fmt/texinfoparser/comments.norm b/t/fmt/texinfoparser/comments.norm
new file mode 100644
index 00000000..5d241722
--- /dev/null
+++ b/t/fmt/texinfoparser/comments.norm
@@ -0,0 +1,16 @@
+\input texinfo   @c -*-texinfo-*-
+@comment $Id@w{$}
+@comment %**start of header
+@settitle GNU Sample 1.0
+@syncodeindex pg cp
+@comment %**end of header
+
+@node Top
+@top GNU Sample
+
+@c TRANSLATORS: This is a comment for the translators
+@comment TRANSLATORS: This one also
+@c Not this one, it should not be shown to the translators
+This manual is for GNU Sample (version 1.0, UPDATED).
+
+@bye
diff --git a/t/fmt/texinfoparser/comments.po b/t/fmt/texinfoparser/comments.po
new file mode 100644
index 00000000..de9ab3a2
--- /dev/null
+++ b/t/fmt/texinfoparser/comments.po
@@ -0,0 +1,77 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @comment
+#: comments.texi:2
+#, no-wrap
+msgid "$Id@w{$}"
+msgstr "$ID@W{$}"
+
+#. type: line_arg 1 in @comment
+#: comments.texi:3
+#, no-wrap
+msgid "%**start of header"
+msgstr "%**START OF HEADER"
+
+#. type: line_arg 1 in @settitle
+#: comments.texi:4
+#, no-wrap
+msgid "GNU Sample 1.0"
+msgstr "GNU SAMPLE 1.0"
+
+#. type: line_arg 1 in @comment
+#: comments.texi:6
+#, no-wrap
+msgid "%**end of header"
+msgstr "%**END OF HEADER"
+
+#. type: line_arg 1 in @node
+#: comments.texi:8
+#, no-wrap
+msgid "Top"
+msgstr "TOP"
+
+#. type: line_arg 1 in @top
+#: comments.texi:9
+#, no-wrap
+msgid "GNU Sample"
+msgstr "GNU SAMPLE"
+
+#. type: line_arg 1 in @c
+#: comments.texi:11
+#, no-wrap
+msgid "TRANSLATORS: This is a comment for the translators"
+msgstr "TRANSLATORS: THIS IS A COMMENT FOR THE TRANSLATORS"
+
+#. type: line_arg 1 in @comment
+#: comments.texi:12
+#, no-wrap
+msgid "TRANSLATORS: This one also"
+msgstr "TRANSLATORS: THIS ONE ALSO"
+
+#. type: line_arg 1 in @c
+#: comments.texi:13
+#, no-wrap
+msgid "Not this one, it should not be shown to the translators"
+msgstr "NOT THIS ONE, IT SHOULD NOT BE SHOWN TO THE TRANSLATORS"
+
+#. type: paragraph
+#: comments.texi:14
+#, no-wrap
+msgid "This manual is for GNU Sample (version 1.0, UPDATED)."
+msgstr "THIS MANUAL IS FOR GNU SAMPLE (VERSION 1.0, UPDATED)."
diff --git a/t/fmt/texinfoparser/comments.pot b/t/fmt/texinfoparser/comments.pot
new file mode 100644
index 00000000..7a799fe8
--- /dev/null
+++ b/t/fmt/texinfoparser/comments.pot
@@ -0,0 +1,77 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @comment
+#: comments.texi:2
+#, no-wrap
+msgid "$Id@w{$}"
+msgstr ""
+
+#. type: line_arg 1 in @comment
+#: comments.texi:3
+#, no-wrap
+msgid "%**start of header"
+msgstr ""
+
+#. type: line_arg 1 in @settitle
+#: comments.texi:4
+#, no-wrap
+msgid "GNU Sample 1.0"
+msgstr ""
+
+#. type: line_arg 1 in @comment
+#: comments.texi:6
+#, no-wrap
+msgid "%**end of header"
+msgstr ""
+
+#. type: line_arg 1 in @node
+#: comments.texi:8
+#, no-wrap
+msgid "Top"
+msgstr ""
+
+#. type: line_arg 1 in @top
+#: comments.texi:9
+#, no-wrap
+msgid "GNU Sample"
+msgstr ""
+
+#. type: line_arg 1 in @c
+#: comments.texi:11
+#, no-wrap
+msgid "TRANSLATORS: This is a comment for the translators"
+msgstr ""
+
+#. type: line_arg 1 in @comment
+#: comments.texi:12
+#, no-wrap
+msgid "TRANSLATORS: This one also"
+msgstr ""
+
+#. type: line_arg 1 in @c
+#: comments.texi:13
+#, no-wrap
+msgid "Not this one, it should not be shown to the translators"
+msgstr ""
+
+#. type: paragraph
+#: comments.texi:14
+#, no-wrap
+msgid "This manual is for GNU Sample (version 1.0, UPDATED)."
+msgstr ""
diff --git a/t/fmt/texinfoparser/comments.texi b/t/fmt/texinfoparser/comments.texi
new file mode 100644
index 00000000..5d241722
--- /dev/null
+++ b/t/fmt/texinfoparser/comments.texi
@@ -0,0 +1,16 @@
+\input texinfo   @c -*-texinfo-*-
+@comment $Id@w{$}
+@comment %**start of header
+@settitle GNU Sample 1.0
+@syncodeindex pg cp
+@comment %**end of header
+
+@node Top
+@top GNU Sample
+
+@c TRANSLATORS: This is a comment for the translators
+@comment TRANSLATORS: This one also
+@c Not this one, it should not be shown to the translators
+This manual is for GNU Sample (version 1.0, UPDATED).
+
+@bye
diff --git a/t/fmt/texinfoparser/comments.trans b/t/fmt/texinfoparser/comments.trans
new file mode 100644
index 00000000..94a24e4c
--- /dev/null
+++ b/t/fmt/texinfoparser/comments.trans
@@ -0,0 +1,16 @@
+\input texinfo   @c -*-texinfo-*-
+@comment $ID@W{$}
+@comment %**START OF HEADER
+@settitle GNU SAMPLE 1.0
+@syncodeindex pg cp
+@comment %**END OF HEADER
+
+@node TOP
+@top GNU SAMPLE
+
+@c TRANSLATORS: THIS IS A COMMENT FOR THE TRANSLATORS
+@comment TRANSLATORS: THIS ONE ALSO
+@c NOT THIS ONE, IT SHOULD NOT BE SHOWN TO THE TRANSLATORS
+THIS MANUAL IS FOR GNU SAMPLE (VERSION 1.0, UPDATED).
+
+@bye
diff --git a/t/fmt/texinfoparser/conditionals.norm b/t/fmt/texinfoparser/conditionals.norm
new file mode 100644
index 00000000..150d9059
--- /dev/null
+++ b/t/fmt/texinfoparser/conditionals.norm
@@ -0,0 +1,38 @@
+
+@iftex @comment on iftex
+In iftex
+@end iftex @comment on end iftex
+
+@ifnottex
+In ifnotex
+@end ifnottex @comment on end ifnotex
+
+@ifhtml @comment on ifhtml
+in ifhtml
+@end ifhtml @comment on end ifhtml
+
+@ifnothtml
+in ifnohtml
+@end ifnothtml
+
+@example
+My code
+@iftex @comment on iftex in example
+In iftex in example
+@end iftex @comment on end iftex in example
+ 
+@ifnottex @comment on ifnottex in example
+In ifnotex in example
+@end ifnottex @comment on end ifnotex in example
+after my code
+@end example
+
+@set toto a
+
+@ifset toto @comment on ifset
+in ifset toto
+@end ifset @comment on end ifset
+
+@ifclear toto @comment on ifclear
+in in ifclear toto
+@end ifclear @comment on end ifclear
diff --git a/t/fmt/texinfoparser/conditionals.po b/t/fmt/texinfoparser/conditionals.po
new file mode 100644
index 00000000..8b018aa8
--- /dev/null
+++ b/t/fmt/texinfoparser/conditionals.po
@@ -0,0 +1,125 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: @iftex
+#: conditionals.texi:2
+#, no-wrap
+msgid ""
+"@iftex @comment on iftex\n"
+"In iftex\n"
+"@end iftex @comment on end iftex"
+msgstr ""
+"@IFTEX @COMMENT ON IFTEX\n"
+"IN IFTEX\n"
+"@END IFTEX @COMMENT ON END IFTEX"
+
+#. type: paragraph
+#: conditionals.texi:7
+#, no-wrap
+msgid ""
+"In ifnotex\n"
+"@end ifnottex @comment on end ifnotex"
+msgstr ""
+"IN IFNOTEX\n"
+"@END IFNOTTEX @COMMENT ON END IFNOTEX"
+
+#. type: line_arg 1 in @comment
+#: conditionals.texi:10
+#, no-wrap
+msgid "on ifhtml"
+msgstr "ON IFHTML"
+
+#. type: paragraph
+#: conditionals.texi:11
+#, no-wrap
+msgid ""
+"in ifhtml\n"
+"@end ifhtml @comment on end ifhtml"
+msgstr ""
+"IN IFHTML\n"
+"@END IFHTML @COMMENT ON END IFHTML"
+
+#. type: @ifnothtml
+#: conditionals.texi:14
+#, no-wrap
+msgid ""
+"@ifnothtml\n"
+"in ifnohtml\n"
+"@end ifnothtml"
+msgstr ""
+"@IFNOTHTML\n"
+"IN IFNOHTML\n"
+"@END IFNOTHTML"
+
+#. type: preformatted
+#: conditionals.texi:19
+#, no-wrap
+msgid ""
+"My code\n"
+"@iftex @comment on iftex in example\n"
+"In iftex in example\n"
+"@end iftex @comment on end iftex in example\n"
+" \n"
+"@ifnottex @comment on ifnottex in example\n"
+"In ifnotex in example\n"
+"@end ifnottex @comment on end ifnotex in example\n"
+"after my code"
+msgstr ""
+"MY CODE\n"
+"@IFTEX @COMMENT ON IFTEX IN EXAMPLE\n"
+"IN IFTEX IN EXAMPLE\n"
+"@END IFTEX @COMMENT ON END IFTEX IN EXAMPLE\n"
+" \n"
+"@IFNOTTEX @COMMENT ON IFNOTTEX IN EXAMPLE\n"
+"IN IFNOTEX IN EXAMPLE\n"
+"@END IFNOTTEX @COMMENT ON END IFNOTEX IN EXAMPLE\n"
+"AFTER MY CODE"
+
+#. type: @set
+#: conditionals.texi:30
+#, no-wrap
+msgid "@set toto a"
+msgstr "@SET TOTO A"
+
+#. type: line_arg 1 in @comment
+#: conditionals.texi:32
+#, no-wrap
+msgid "on ifset"
+msgstr "ON IFSET"
+
+#. type: paragraph
+#: conditionals.texi:33
+#, no-wrap
+msgid ""
+"in ifset toto\n"
+"@end ifset @comment on end ifset"
+msgstr ""
+"IN IFSET TOTO\n"
+"@END IFSET @COMMENT ON END IFSET"
+
+#. type: @ifclear
+#: conditionals.texi:36
+#, no-wrap
+msgid ""
+"@ifclear toto @comment on ifclear\n"
+"in in ifclear toto\n"
+"@end ifclear @comment on end ifclear"
+msgstr ""
+"@IFCLEAR TOTO @COMMENT ON IFCLEAR\n"
+"IN IN IFCLEAR TOTO\n"
+"@END IFCLEAR @COMMENT ON END IFCLEAR"
diff --git a/t/fmt/texinfoparser/conditionals.pot b/t/fmt/texinfoparser/conditionals.pot
new file mode 100644
index 00000000..311fd7da
--- /dev/null
+++ b/t/fmt/texinfoparser/conditionals.pot
@@ -0,0 +1,101 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: @iftex
+#: conditionals.texi:2
+#, no-wrap
+msgid ""
+"@iftex @comment on iftex\n"
+"In iftex\n"
+"@end iftex @comment on end iftex"
+msgstr ""
+
+#. type: paragraph
+#: conditionals.texi:7
+#, no-wrap
+msgid ""
+"In ifnotex\n"
+"@end ifnottex @comment on end ifnotex"
+msgstr ""
+
+#. type: line_arg 1 in @comment
+#: conditionals.texi:10
+#, no-wrap
+msgid "on ifhtml"
+msgstr ""
+
+#. type: paragraph
+#: conditionals.texi:11
+#, no-wrap
+msgid ""
+"in ifhtml\n"
+"@end ifhtml @comment on end ifhtml"
+msgstr ""
+
+#. type: @ifnothtml
+#: conditionals.texi:14
+#, no-wrap
+msgid ""
+"@ifnothtml\n"
+"in ifnohtml\n"
+"@end ifnothtml"
+msgstr ""
+
+#. type: preformatted
+#: conditionals.texi:19
+#, no-wrap
+msgid ""
+"My code\n"
+"@iftex @comment on iftex in example\n"
+"In iftex in example\n"
+"@end iftex @comment on end iftex in example\n"
+" \n"
+"@ifnottex @comment on ifnottex in example\n"
+"In ifnotex in example\n"
+"@end ifnottex @comment on end ifnotex in example\n"
+"after my code"
+msgstr ""
+
+#. type: @set
+#: conditionals.texi:30
+#, no-wrap
+msgid "@set toto a"
+msgstr ""
+
+#. type: line_arg 1 in @comment
+#: conditionals.texi:32
+#, no-wrap
+msgid "on ifset"
+msgstr ""
+
+#. type: paragraph
+#: conditionals.texi:33
+#, no-wrap
+msgid ""
+"in ifset toto\n"
+"@end ifset @comment on end ifset"
+msgstr ""
+
+#. type: @ifclear
+#: conditionals.texi:36
+#, no-wrap
+msgid ""
+"@ifclear toto @comment on ifclear\n"
+"in in ifclear toto\n"
+"@end ifclear @comment on end ifclear"
+msgstr ""
diff --git a/t/fmt/texinfoparser/conditionals.texi b/t/fmt/texinfoparser/conditionals.texi
new file mode 100644
index 00000000..150d9059
--- /dev/null
+++ b/t/fmt/texinfoparser/conditionals.texi
@@ -0,0 +1,38 @@
+
+@iftex @comment on iftex
+In iftex
+@end iftex @comment on end iftex
+
+@ifnottex
+In ifnotex
+@end ifnottex @comment on end ifnotex
+
+@ifhtml @comment on ifhtml
+in ifhtml
+@end ifhtml @comment on end ifhtml
+
+@ifnothtml
+in ifnohtml
+@end ifnothtml
+
+@example
+My code
+@iftex @comment on iftex in example
+In iftex in example
+@end iftex @comment on end iftex in example
+ 
+@ifnottex @comment on ifnottex in example
+In ifnotex in example
+@end ifnottex @comment on end ifnotex in example
+after my code
+@end example
+
+@set toto a
+
+@ifset toto @comment on ifset
+in ifset toto
+@end ifset @comment on end ifset
+
+@ifclear toto @comment on ifclear
+in in ifclear toto
+@end ifclear @comment on end ifclear
diff --git a/t/fmt/texinfoparser/conditionals.trans b/t/fmt/texinfoparser/conditionals.trans
new file mode 100644
index 00000000..ac89ef8d
--- /dev/null
+++ b/t/fmt/texinfoparser/conditionals.trans
@@ -0,0 +1,38 @@
+
+@IFTEX @COMMENT ON IFTEX
+IN IFTEX
+@END IFTEX @COMMENT ON END IFTEX
+
+@ifnottex
+IN IFNOTEX
+@END IFNOTTEX @COMMENT ON END IFNOTEX
+
+@ifhtml @comment ON IFHTML
+IN IFHTML
+@END IFHTML @COMMENT ON END IFHTML
+
+@IFNOTHTML
+IN IFNOHTML
+@END IFNOTHTML
+
+@example
+MY CODE
+@IFTEX @COMMENT ON IFTEX IN EXAMPLE
+IN IFTEX IN EXAMPLE
+@END IFTEX @COMMENT ON END IFTEX IN EXAMPLE
+ 
+@IFNOTTEX @COMMENT ON IFNOTTEX IN EXAMPLE
+IN IFNOTEX IN EXAMPLE
+@END IFNOTTEX @COMMENT ON END IFNOTEX IN EXAMPLE
+AFTER MY CODE
+@end example
+
+@SET TOTO A
+
+@ifset toto @comment ON IFSET
+IN IFSET TOTO
+@END IFSET @COMMENT ON END IFSET
+
+@IFCLEAR TOTO @COMMENT ON IFCLEAR
+IN IN IFCLEAR TOTO
+@END IFCLEAR @COMMENT ON END IFCLEAR
diff --git a/t/fmt/texinfoparser/invalidlineecount.norm b/t/fmt/texinfoparser/invalidlineecount.norm
new file mode 100644
index 00000000..04a367a0
--- /dev/null
+++ b/t/fmt/texinfoparser/invalidlineecount.norm
@@ -0,0 +1,15 @@
+
+@ignore
+Test invalid Texinfo code that leads to a difference in line
+number in the code obtained from the tree representation, with a fixed
+source, compared to the original Texinfo code.
+@end ignore
+
+@set a
+ 
+@ifset a
+@ifclear ok @c - ok, ignored
+@end junky   - ok, ignored
+@c WRONG - missing @end ifset.
+
+@chapter chap
diff --git a/t/fmt/texinfoparser/invalidlineecount.norm.stderr b/t/fmt/texinfoparser/invalidlineecount.norm.stderr
new file mode 100644
index 00000000..05a558b6
--- /dev/null
+++ b/t/fmt/texinfoparser/invalidlineecount.norm.stderr
@@ -0,0 +1,4 @@
+po4a::texinfo: invalidlineecount.texi:12: warning: unknown @end junky
+po4a::texinfo: invalidlineecount.texi:13: unmatched `@end ifset'
+po4a::texinfo: invalidlineecount.texi:16: expected @end ifclear
+po4a::texinfo: invalidlineecount.texi:16: expected @end ifset
diff --git a/t/fmt/texinfoparser/invalidlineecount.po b/t/fmt/texinfoparser/invalidlineecount.po
new file mode 100644
index 00000000..96844949
--- /dev/null
+++ b/t/fmt/texinfoparser/invalidlineecount.po
@@ -0,0 +1,57 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: @ignore
+#: invalidlineecount.texi:2
+#, no-wrap
+msgid ""
+"@ignore\n"
+"Test invalid Texinfo code that leads to a difference in line\n"
+"number in the code obtained from the tree representation, with a fixed\n"
+"source, compared to the original Texinfo code.\n"
+"@end ignore"
+msgstr ""
+"@IGNORE\n"
+"TEST INVALID TEXINFO CODE THAT LEADS TO A DIFFERENCE IN LINE\n"
+"NUMBER IN THE CODE OBTAINED FROM THE TREE REPRESENTATION, WITH A FIXED\n"
+"SOURCE, COMPARED TO THE ORIGINAL TEXINFO CODE.\n"
+"@END IGNORE"
+
+#. type: @set
+#: invalidlineecount.texi:8
+#, no-wrap
+msgid "@set a"
+msgstr "@SET A"
+
+#. type: line_arg 1 in @c
+#: invalidlineecount.texi:11
+#, no-wrap
+msgid "- ok, ignored"
+msgstr "- OK, IGNORED"
+
+#. type: line_arg 1 in @c
+#: invalidlineecount.texi:13
+#, no-wrap
+msgid "WRONG - missing @end ifset."
+msgstr "WRONG - MISSING @END IFSET."
+
+#. type: line_arg 1 in @chapter
+#: invalidlineecount.texi:16
+#, no-wrap
+msgid "chap"
+msgstr "CHAP"
diff --git a/t/fmt/texinfoparser/invalidlineecount.pot b/t/fmt/texinfoparser/invalidlineecount.pot
new file mode 100644
index 00000000..c8277f6e
--- /dev/null
+++ b/t/fmt/texinfoparser/invalidlineecount.pot
@@ -0,0 +1,52 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: @ignore
+#: invalidlineecount.texi:2
+#, no-wrap
+msgid ""
+"@ignore\n"
+"Test invalid Texinfo code that leads to a difference in line\n"
+"number in the code obtained from the tree representation, with a fixed\n"
+"source, compared to the original Texinfo code.\n"
+"@end ignore"
+msgstr ""
+
+#. type: @set
+#: invalidlineecount.texi:8
+#, no-wrap
+msgid "@set a"
+msgstr ""
+
+#. type: line_arg 1 in @c
+#: invalidlineecount.texi:11
+#, no-wrap
+msgid "- ok, ignored"
+msgstr ""
+
+#. type: line_arg 1 in @c
+#: invalidlineecount.texi:13
+#, no-wrap
+msgid "WRONG - missing @end ifset."
+msgstr ""
+
+#. type: line_arg 1 in @chapter
+#: invalidlineecount.texi:16
+#, no-wrap
+msgid "chap"
+msgstr ""
diff --git a/t/fmt/texinfoparser/invalidlineecount.texi b/t/fmt/texinfoparser/invalidlineecount.texi
new file mode 100644
index 00000000..efb8efb2
--- /dev/null
+++ b/t/fmt/texinfoparser/invalidlineecount.texi
@@ -0,0 +1,16 @@
+
+@ignore
+Test invalid Texinfo code that leads to a difference in line
+number in the code obtained from the tree representation, with a fixed
+source, compared to the original Texinfo code.
+@end ignore
+
+@set a
+ 
+@ifset a
+@ifclear ok @c - ok, ignored
+@end junky   - ok, ignored
+@end ifset
+@c WRONG - missing @end ifset.
+
+@chapter chap
diff --git a/t/fmt/texinfoparser/invalidlineecount.trans b/t/fmt/texinfoparser/invalidlineecount.trans
new file mode 100644
index 00000000..8625cfc8
--- /dev/null
+++ b/t/fmt/texinfoparser/invalidlineecount.trans
@@ -0,0 +1,15 @@
+
+@IGNORE
+TEST INVALID TEXINFO CODE THAT LEADS TO A DIFFERENCE IN LINE
+NUMBER IN THE CODE OBTAINED FROM THE TREE REPRESENTATION, WITH A FIXED
+SOURCE, COMPARED TO THE ORIGINAL TEXINFO CODE.
+@END IGNORE
+
+@SET A
+ 
+@ifset a
+@ifclear ok @c - OK, IGNORED
+@end junky   - ok, ignored
+@c WRONG - MISSING @END IFSET.
+
+@chapter CHAP
diff --git a/t/fmt/texinfoparser/invalidlineecount.trans.stderr b/t/fmt/texinfoparser/invalidlineecount.trans.stderr
new file mode 100644
index 00000000..05a558b6
--- /dev/null
+++ b/t/fmt/texinfoparser/invalidlineecount.trans.stderr
@@ -0,0 +1,4 @@
+po4a::texinfo: invalidlineecount.texi:12: warning: unknown @end junky
+po4a::texinfo: invalidlineecount.texi:13: unmatched `@end ifset'
+po4a::texinfo: invalidlineecount.texi:16: expected @end ifclear
+po4a::texinfo: invalidlineecount.texi:16: expected @end ifset
diff --git a/t/fmt/texinfoparser/linemacro.norm b/t/fmt/texinfoparser/linemacro.norm
new file mode 100644
index 00000000..b09d53f3
--- /dev/null
+++ b/t/fmt/texinfoparser/linemacro.norm
@@ -0,0 +1,90 @@
+
+@node Top
+@top test linemacro, based on Texinfo tta t/*linemacro.t tests
+
+@linemacro mycommand {a, b, c, d}
+first \a\
+second \b\
+third \c\
+@defline \a\ \d\
+@end linemacro
+ 
+@defblock
+@mycommand {Name} @verb{: in verb :} {A @verb{| in bracketed |} } other {j}
+@end defblock
+
+@linemacro myothercommand {a, b, c}
+\a\, \b\ \c\
+@end linemacro
+ 
+@* @myothercommand @anchor{aa} definite and @code{more}
+ 
+Some text @myothercommand {a
+  protected} in @var{the
+ call}
+and after.
+
+@linemacro defbuiltin {symbol, rest}
+@defline \symbol\ f r
+@defline expand Builtin and \rest\
+@end linemacro
+ 
+@defblock
+@defbuiltin {my foo} a last {} arg{ument}
+ 
+@defbuiltin {my foo} {} {}
+ 
+@defbuiltin {my foo} {second arg} remaining on {line}
+@end defblock
+
+@linemacro test {first, rest}
+@deffn Function \first\ \rest\
+something
+@end deffn
+@end linemacro
+ 
+@test foo (bar, baz)@
+ continuation line
+ 
+@test foo@ b (bar, baz) rest@ and more
+ 
+@test foo (bar, baz)@@
+ another with double at
+
+@linemacro mylinecommand {first, second, rest}
+@defblock
+@defline category \first\ A \second\ B \rest\
+@end defblock
+@end linemacro
+ 
+@mylinecommand{a b}{c d}{rest}
+
+@mylinecommand {  a } { d  } {   rest}
+
+@linemacro inside {a, b, rest}
+inside {\a\ operator \b\} \rest\
+@end linemacro
+ 
+@linemacro outside {one, two, three}
+@defline \one\ {\two\} \three\
+@cindex \two\
+@end linemacro
+ 
+@defblock
+@outside {type} {a function} @inside {X} {Y} ( remaining, type typed )
+@end defblock
+ 
+@linemacro lm {a, b, c}
+first |\a\|
+second |\b\|
+third |\c\|
+@end linemacro
+ 
+@lm {something protected} @c comment {in braces}
+  
+@lm@c comment early n l m
+ 
+@lm {aaa
+  } rest @comment on second {line comment}
+
+
diff --git a/t/fmt/texinfoparser/linemacro.po b/t/fmt/texinfoparser/linemacro.po
new file mode 100644
index 00000000..1e5658a4
--- /dev/null
+++ b/t/fmt/texinfoparser/linemacro.po
@@ -0,0 +1,195 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @node
+#: linemacro.texi:2
+#, no-wrap
+msgid "Top"
+msgstr "TOP"
+
+#. type: line_arg 1 in @top
+#: linemacro.texi:3
+#, no-wrap
+msgid "test linemacro, based on Texinfo tta t/*linemacro.t tests"
+msgstr "TEST LINEMACRO, BASED ON TEXINFO TTA T/*LINEMACRO.T TESTS"
+
+#. type: @linemacro
+#: linemacro.texi:5
+#, no-wrap
+msgid ""
+"@linemacro mycommand {a, b, c, d}\n"
+"first \\a\\\n"
+"second \\b\\\n"
+"third \\c\\\n"
+"@defline \\a\\ \\d\\\n"
+"@end linemacro"
+msgstr ""
+"@LINEMACRO MYCOMMAND {A, B, C, D}\n"
+"FIRST \\a\\\n"
+"SECOND \\b\\\n"
+"THIRD \\c\\\n"
+"@DEFLINE \\a\\ \\d\\\n"
+"@END LINEMACRO"
+
+#. type: paragraph
+#: linemacro.texi:13
+#, no-wrap
+msgid "@mycommand {Name} @verb{: in verb :} {A @verb{| in bracketed |} } other {j}"
+msgstr "@MYCOMMAND {NAME} @VERB{: IN VERB :} {A @VERB{| IN BRACKETED |} } OTHER {J}"
+
+#. type: @linemacro
+#: linemacro.texi:16
+#, no-wrap
+msgid ""
+"@linemacro myothercommand {a, b, c}\n"
+"\\a\\, \\b\\ \\c\\\n"
+"@end linemacro"
+msgstr ""
+"@LINEMACRO MYOTHERCOMMAND {A, B, C}\n"
+"\\a\\, \\b\\ \\c\\\n"
+"@END LINEMACRO"
+
+#. type: paragraph
+#: linemacro.texi:22
+#, no-wrap
+msgid ""
+"Some text @myothercommand {a\n"
+"  protected} in @var{the\n"
+" call}\n"
+"and after."
+msgstr ""
+"SOME TEXT @MYOTHERCOMMAND {A\n"
+"  PROTECTED} IN @VAR{THE\n"
+" CALL}\n"
+"AND AFTER."
+
+#. type: @linemacro
+#: linemacro.texi:27
+#, no-wrap
+msgid ""
+"@linemacro defbuiltin {symbol, rest}\n"
+"@defline \\symbol\\ f r\n"
+"@defline expand Builtin and \\rest\\\n"
+"@end linemacro"
+msgstr ""
+"@LINEMACRO DEFBUILTIN {SYMBOL, REST}\n"
+"@DEFLINE \\sYMBOL\\ F R\n"
+"@DEFLINE EXPAND BUILTIN AND \\rEST\\\n"
+"@END LINEMACRO"
+
+#. type: @linemacro
+#: linemacro.texi:40
+#, no-wrap
+msgid ""
+"@linemacro test {first, rest}\n"
+"@deffn Function \\first\\ \\rest\\\n"
+"something\n"
+"@end deffn\n"
+"@end linemacro"
+msgstr ""
+"@LINEMACRO TEST {FIRST, REST}\n"
+"@DEFFN FUNCTION \\fIRST\\ \\rEST\\\n"
+"SOMETHING\n"
+"@END DEFFN\n"
+"@END LINEMACRO"
+
+#. type: paragraph
+#: linemacro.texi:52
+#, no-wrap
+msgid "another with double at"
+msgstr "ANOTHER WITH DOUBLE AT"
+
+#. type: @linemacro
+#: linemacro.texi:54
+#, no-wrap
+msgid ""
+"@linemacro mylinecommand {first, second, rest}\n"
+"@defblock\n"
+"@defline category \\first\\ A \\second\\ B \\rest\\\n"
+"@end defblock\n"
+"@end linemacro"
+msgstr ""
+"@LINEMACRO MYLINECOMMAND {FIRST, SECOND, REST}\n"
+"@DEFBLOCK\n"
+"@DEFLINE CATEGORY \\fIRST\\ A \\sECOND\\ B \\rEST\\\n"
+"@END DEFBLOCK\n"
+"@END LINEMACRO"
+
+#. type: @linemacro
+#: linemacro.texi:64
+#, no-wrap
+msgid ""
+"@linemacro inside {a, b, rest}\n"
+"inside {\\a\\ operator \\b\\} \\rest\\\n"
+"@end linemacro"
+msgstr ""
+"@LINEMACRO INSIDE {A, B, REST}\n"
+"INSIDE {\\a\\ OPERATOR \\b\\} \\rEST\\\n"
+"@END LINEMACRO"
+
+#. type: @linemacro
+#: linemacro.texi:68
+#, no-wrap
+msgid ""
+"@linemacro outside {one, two, three}\n"
+"@defline \\one\\ {\\two\\} \\three\\\n"
+"@cindex \\two\\\n"
+"@end linemacro"
+msgstr ""
+"@LINEMACRO OUTSIDE {ONE, TWO, THREE}\n"
+"@DEFLINE \\oNE\\ {\\tWO\\} \\tHREE\\\n"
+"@CINDEX \\tWO\\\n"
+"@END LINEMACRO"
+
+#. type: @linemacro
+#: linemacro.texi:77
+#, no-wrap
+msgid ""
+"@linemacro lm {a, b, c}\n"
+"first |\\a\\|\n"
+"second |\\b\\|\n"
+"third |\\c\\|\n"
+"@end linemacro"
+msgstr ""
+"@LINEMACRO LM {A, B, C}\n"
+"FIRST |\\a\\|\n"
+"SECOND |\\b\\|\n"
+"THIRD |\\c\\|\n"
+"@END LINEMACRO"
+
+#. type: paragraph
+#: linemacro.texi:83
+#, no-wrap
+msgid "@lm {something protected} @c comment {in braces}"
+msgstr "@LM {SOMETHING PROTECTED} @C COMMENT {IN BRACES}"
+
+#. type: paragraph
+#: linemacro.texi:85
+#, no-wrap
+msgid "@lm@c comment early n l m"
+msgstr "@LM@C COMMENT EARLY N L M"
+
+#. type: paragraph
+#: linemacro.texi:87
+#, no-wrap
+msgid ""
+"@lm {aaa\n"
+"  } rest @comment on second {line comment}"
+msgstr ""
+"@LM {AAA\n"
+"  } REST @COMMENT ON SECOND {LINE COMMENT}"
diff --git a/t/fmt/texinfoparser/linemacro.pot b/t/fmt/texinfoparser/linemacro.pot
new file mode 100644
index 00000000..6b4b4faf
--- /dev/null
+++ b/t/fmt/texinfoparser/linemacro.pot
@@ -0,0 +1,154 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @node
+#: linemacro.texi:2
+#, no-wrap
+msgid "Top"
+msgstr ""
+
+#. type: line_arg 1 in @top
+#: linemacro.texi:3
+#, no-wrap
+msgid "test linemacro, based on Texinfo tta t/*linemacro.t tests"
+msgstr ""
+
+#. type: @linemacro
+#: linemacro.texi:5
+#, no-wrap
+msgid ""
+"@linemacro mycommand {a, b, c, d}\n"
+"first \\a\\\n"
+"second \\b\\\n"
+"third \\c\\\n"
+"@defline \\a\\ \\d\\\n"
+"@end linemacro"
+msgstr ""
+
+#. type: paragraph
+#: linemacro.texi:13
+#, no-wrap
+msgid "@mycommand {Name} @verb{: in verb :} {A @verb{| in bracketed |} } other {j}"
+msgstr ""
+
+#. type: @linemacro
+#: linemacro.texi:16
+#, no-wrap
+msgid ""
+"@linemacro myothercommand {a, b, c}\n"
+"\\a\\, \\b\\ \\c\\\n"
+"@end linemacro"
+msgstr ""
+
+#. type: paragraph
+#: linemacro.texi:22
+#, no-wrap
+msgid ""
+"Some text @myothercommand {a\n"
+"  protected} in @var{the\n"
+" call}\n"
+"and after."
+msgstr ""
+
+#. type: @linemacro
+#: linemacro.texi:27
+#, no-wrap
+msgid ""
+"@linemacro defbuiltin {symbol, rest}\n"
+"@defline \\symbol\\ f r\n"
+"@defline expand Builtin and \\rest\\\n"
+"@end linemacro"
+msgstr ""
+
+#. type: @linemacro
+#: linemacro.texi:40
+#, no-wrap
+msgid ""
+"@linemacro test {first, rest}\n"
+"@deffn Function \\first\\ \\rest\\\n"
+"something\n"
+"@end deffn\n"
+"@end linemacro"
+msgstr ""
+
+#. type: paragraph
+#: linemacro.texi:52
+#, no-wrap
+msgid "another with double at"
+msgstr ""
+
+#. type: @linemacro
+#: linemacro.texi:54
+#, no-wrap
+msgid ""
+"@linemacro mylinecommand {first, second, rest}\n"
+"@defblock\n"
+"@defline category \\first\\ A \\second\\ B \\rest\\\n"
+"@end defblock\n"
+"@end linemacro"
+msgstr ""
+
+#. type: @linemacro
+#: linemacro.texi:64
+#, no-wrap
+msgid ""
+"@linemacro inside {a, b, rest}\n"
+"inside {\\a\\ operator \\b\\} \\rest\\\n"
+"@end linemacro"
+msgstr ""
+
+#. type: @linemacro
+#: linemacro.texi:68
+#, no-wrap
+msgid ""
+"@linemacro outside {one, two, three}\n"
+"@defline \\one\\ {\\two\\} \\three\\\n"
+"@cindex \\two\\\n"
+"@end linemacro"
+msgstr ""
+
+#. type: @linemacro
+#: linemacro.texi:77
+#, no-wrap
+msgid ""
+"@linemacro lm {a, b, c}\n"
+"first |\\a\\|\n"
+"second |\\b\\|\n"
+"third |\\c\\|\n"
+"@end linemacro"
+msgstr ""
+
+#. type: paragraph
+#: linemacro.texi:83
+#, no-wrap
+msgid "@lm {something protected} @c comment {in braces}"
+msgstr ""
+
+#. type: paragraph
+#: linemacro.texi:85
+#, no-wrap
+msgid "@lm@c comment early n l m"
+msgstr ""
+
+#. type: paragraph
+#: linemacro.texi:87
+#, no-wrap
+msgid ""
+"@lm {aaa\n"
+"  } rest @comment on second {line comment}"
+msgstr ""
diff --git a/t/fmt/texinfoparser/linemacro.texi b/t/fmt/texinfoparser/linemacro.texi
new file mode 100644
index 00000000..b09d53f3
--- /dev/null
+++ b/t/fmt/texinfoparser/linemacro.texi
@@ -0,0 +1,90 @@
+
+@node Top
+@top test linemacro, based on Texinfo tta t/*linemacro.t tests
+
+@linemacro mycommand {a, b, c, d}
+first \a\
+second \b\
+third \c\
+@defline \a\ \d\
+@end linemacro
+ 
+@defblock
+@mycommand {Name} @verb{: in verb :} {A @verb{| in bracketed |} } other {j}
+@end defblock
+
+@linemacro myothercommand {a, b, c}
+\a\, \b\ \c\
+@end linemacro
+ 
+@* @myothercommand @anchor{aa} definite and @code{more}
+ 
+Some text @myothercommand {a
+  protected} in @var{the
+ call}
+and after.
+
+@linemacro defbuiltin {symbol, rest}
+@defline \symbol\ f r
+@defline expand Builtin and \rest\
+@end linemacro
+ 
+@defblock
+@defbuiltin {my foo} a last {} arg{ument}
+ 
+@defbuiltin {my foo} {} {}
+ 
+@defbuiltin {my foo} {second arg} remaining on {line}
+@end defblock
+
+@linemacro test {first, rest}
+@deffn Function \first\ \rest\
+something
+@end deffn
+@end linemacro
+ 
+@test foo (bar, baz)@
+ continuation line
+ 
+@test foo@ b (bar, baz) rest@ and more
+ 
+@test foo (bar, baz)@@
+ another with double at
+
+@linemacro mylinecommand {first, second, rest}
+@defblock
+@defline category \first\ A \second\ B \rest\
+@end defblock
+@end linemacro
+ 
+@mylinecommand{a b}{c d}{rest}
+
+@mylinecommand {  a } { d  } {   rest}
+
+@linemacro inside {a, b, rest}
+inside {\a\ operator \b\} \rest\
+@end linemacro
+ 
+@linemacro outside {one, two, three}
+@defline \one\ {\two\} \three\
+@cindex \two\
+@end linemacro
+ 
+@defblock
+@outside {type} {a function} @inside {X} {Y} ( remaining, type typed )
+@end defblock
+ 
+@linemacro lm {a, b, c}
+first |\a\|
+second |\b\|
+third |\c\|
+@end linemacro
+ 
+@lm {something protected} @c comment {in braces}
+  
+@lm@c comment early n l m
+ 
+@lm {aaa
+  } rest @comment on second {line comment}
+
+
diff --git a/t/fmt/texinfoparser/linemacro.trans b/t/fmt/texinfoparser/linemacro.trans
new file mode 100644
index 00000000..9170c246
--- /dev/null
+++ b/t/fmt/texinfoparser/linemacro.trans
@@ -0,0 +1,90 @@
+
+@node TOP
+@top TEST LINEMACRO, BASED ON TEXINFO TTA T/*LINEMACRO.T TESTS
+
+@LINEMACRO MYCOMMAND {A, B, C, D}
+FIRST \a\
+SECOND \b\
+THIRD \c\
+@DEFLINE \a\ \d\
+@END LINEMACRO
+ 
+@defblock
+@MYCOMMAND {NAME} @VERB{: IN VERB :} {A @VERB{| IN BRACKETED |} } OTHER {J}
+@end defblock
+
+@LINEMACRO MYOTHERCOMMAND {A, B, C}
+\a\, \b\ \c\
+@END LINEMACRO
+ 
+@* @myothercommand @anchor{aa} definite and @code{more}
+ 
+SOME TEXT @MYOTHERCOMMAND {A
+  PROTECTED} IN @VAR{THE
+ CALL}
+AND AFTER.
+
+@LINEMACRO DEFBUILTIN {SYMBOL, REST}
+@DEFLINE \sYMBOL\ F R
+@DEFLINE EXPAND BUILTIN AND \rEST\
+@END LINEMACRO
+ 
+@defblock
+@defbuiltin {my foo} a last {} arg{ument}
+ 
+@defbuiltin {my foo} {} {}
+ 
+@defbuiltin {my foo} {second arg} remaining on {line}
+@end defblock
+
+@LINEMACRO TEST {FIRST, REST}
+@DEFFN FUNCTION \fIRST\ \rEST\
+SOMETHING
+@END DEFFN
+@END LINEMACRO
+ 
+@test foo (bar, baz)@
+ continuation line
+ 
+@test foo@ b (bar, baz) rest@ and more
+ 
+@test foo (bar, baz)@@
+ ANOTHER WITH DOUBLE AT
+
+@LINEMACRO MYLINECOMMAND {FIRST, SECOND, REST}
+@DEFBLOCK
+@DEFLINE CATEGORY \fIRST\ A \sECOND\ B \rEST\
+@END DEFBLOCK
+@END LINEMACRO
+ 
+@mylinecommand{a b}{c d}{rest}
+
+@mylinecommand {  a } { d  } {   rest}
+
+@LINEMACRO INSIDE {A, B, REST}
+INSIDE {\a\ OPERATOR \b\} \rEST\
+@END LINEMACRO
+ 
+@LINEMACRO OUTSIDE {ONE, TWO, THREE}
+@DEFLINE \oNE\ {\tWO\} \tHREE\
+@CINDEX \tWO\
+@END LINEMACRO
+ 
+@defblock
+@outside {type} {a function} @inside {X} {Y} ( remaining, type typed )
+@end defblock
+ 
+@LINEMACRO LM {A, B, C}
+FIRST |\a\|
+SECOND |\b\|
+THIRD |\c\|
+@END LINEMACRO
+ 
+@LM {SOMETHING PROTECTED} @C COMMENT {IN BRACES}
+  
+@LM@C COMMENT EARLY N L M
+ 
+@LM {AAA
+  } REST @COMMENT ON SECOND {LINE COMMENT}
+
+
diff --git a/t/fmt/texinfoparser/longmenu.norm b/t/fmt/texinfoparser/longmenu.norm
new file mode 100644
index 00000000..400e631c
--- /dev/null
+++ b/t/fmt/texinfoparser/longmenu.norm
@@ -0,0 +1,10 @@
+\input texinfo
+
+@menu
+* Compiling For Multiple Architectures::       How to compile Bash for more
+                                               than one kind of system from
+                                               the same source tree.
+@end menu
+
+@node Compiling For Multiple Architectures
+@chapter Compiling For Multiple Architectures
diff --git a/t/fmt/texinfoparser/longmenu.po b/t/fmt/texinfoparser/longmenu.po
new file mode 100644
index 00000000..b4a47ad8
--- /dev/null
+++ b/t/fmt/texinfoparser/longmenu.po
@@ -0,0 +1,39 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: menu_entry
+#: longmenu.texi:4
+#, no-wrap
+msgid ""
+"* Compiling For Multiple Architectures::       How to compile Bash for "
+"more\n"
+"                                               than one kind of system "
+"from\n"
+"                                               the same source tree."
+msgstr ""
+"* COMPILING FOR MULTIPLE ARCHITECTURES::       HOW TO COMPILE BASH FOR "
+"MORE\n"
+"                                               THAN ONE KIND OF SYSTEM "
+"FROM\n"
+"                                               THE SAME SOURCE TREE."
+
+#. type: line_arg 1 in @chapter
+#: longmenu.texi:9 longmenu.texi:10
+#, no-wrap
+msgid "Compiling For Multiple Architectures"
+msgstr "COMPILING FOR MULTIPLE ARCHITECTURES"
diff --git a/t/fmt/texinfoparser/longmenu.pot b/t/fmt/texinfoparser/longmenu.pot
new file mode 100644
index 00000000..6907f915
--- /dev/null
+++ b/t/fmt/texinfoparser/longmenu.pot
@@ -0,0 +1,34 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: menu_entry
+#: longmenu.texi:4
+#, no-wrap
+msgid ""
+"* Compiling For Multiple Architectures::       How to compile Bash for "
+"more\n"
+"                                               than one kind of system "
+"from\n"
+"                                               the same source tree."
+msgstr ""
+
+#. type: line_arg 1 in @chapter
+#: longmenu.texi:9 longmenu.texi:10
+#, no-wrap
+msgid "Compiling For Multiple Architectures"
+msgstr ""
diff --git a/t/fmt/texinfoparser/longmenu.texi b/t/fmt/texinfoparser/longmenu.texi
new file mode 100644
index 00000000..400e631c
--- /dev/null
+++ b/t/fmt/texinfoparser/longmenu.texi
@@ -0,0 +1,10 @@
+\input texinfo
+
+@menu
+* Compiling For Multiple Architectures::       How to compile Bash for more
+                                               than one kind of system from
+                                               the same source tree.
+@end menu
+
+@node Compiling For Multiple Architectures
+@chapter Compiling For Multiple Architectures
diff --git a/t/fmt/texinfoparser/longmenu.trans b/t/fmt/texinfoparser/longmenu.trans
new file mode 100644
index 00000000..08cbc6ae
--- /dev/null
+++ b/t/fmt/texinfoparser/longmenu.trans
@@ -0,0 +1,10 @@
+\input texinfo
+
+@menu
+* COMPILING FOR MULTIPLE ARCHITECTURES::       HOW TO COMPILE BASH FOR MORE
+                                               THAN ONE KIND OF SYSTEM FROM
+                                               THE SAME SOURCE TREE.
+@end menu
+
+@node COMPILING FOR MULTIPLE ARCHITECTURES
+@chapter COMPILING FOR MULTIPLE ARCHITECTURES
diff --git a/t/fmt/texinfoparser/macrovalue.norm b/t/fmt/texinfoparser/macrovalue.norm
new file mode 100644
index 00000000..7220df74
--- /dev/null
+++ b/t/fmt/texinfoparser/macrovalue.norm
@@ -0,0 +1,26 @@
+
+@macro betweenpara {a, b}
+end of prev \b\.
+
+begin of next \a\,
+@end macro
+
+@node Top
+@top test macro and value
+
+there is @betweenpara{farg, secondarg} and more.
+
+there is lot @betweenpara{before empty line
+
+after empty line
+
+@example
+in example
+
+also example
+@end example
+
+, secondarg2
+}.
+
+
diff --git a/t/fmt/texinfoparser/macrovalue.po b/t/fmt/texinfoparser/macrovalue.po
new file mode 100644
index 00000000..3f3620c9
--- /dev/null
+++ b/t/fmt/texinfoparser/macrovalue.po
@@ -0,0 +1,93 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: @macro
+#: macrovalue.texi:2
+#, no-wrap
+msgid ""
+"@macro betweenpara {a, b}\n"
+"end of prev \\b\\.\n"
+"\n"
+"begin of next \\a\\,\n"
+"@end macro"
+msgstr ""
+"@MACRO BETWEENPARA {A, B}\n"
+"END OF PREV \\b\\.\n"
+"\n"
+"BEGIN OF NEXT \\a\\,\n"
+"@END MACRO"
+
+#. type: line_arg 1 in @node
+#: macrovalue.texi:8
+#, no-wrap
+msgid "Top"
+msgstr "TOP"
+
+#. type: line_arg 1 in @top
+#: macrovalue.texi:9
+#, no-wrap
+msgid "test macro and value"
+msgstr "TEST MACRO AND VALUE"
+
+#. type: paragraph
+#: macrovalue.texi:11
+#, no-wrap
+msgid "there is @betweenpara{farg, secondarg}"
+msgstr "THERE IS @BETWEENPARA{FARG, SECONDARG}"
+
+#. type: paragraph
+#: macrovalue.texi:11
+#, no-wrap
+msgid " and more."
+msgstr " AND MORE."
+
+#. type: paragraph
+#: macrovalue.texi:13
+#, no-wrap
+msgid ""
+"there is lot @betweenpara{before empty line\n"
+"\n"
+"after empty line\n"
+"\n"
+"@example\n"
+"in example\n"
+"\n"
+"also example\n"
+"@end example\n"
+"\n"
+", secondarg2\n"
+"}"
+msgstr ""
+"THERE IS LOT @BETWEENPARA{BEFORE EMPTY LINE\n"
+"\n"
+"AFTER EMPTY LINE\n"
+"\n"
+"@EXAMPLE\n"
+"IN EXAMPLE\n"
+"\n"
+"ALSO EXAMPLE\n"
+"@END EXAMPLE\n"
+"\n"
+", SECONDARG2\n"
+"}"
+
+#. type: paragraph
+#: macrovalue.texi:24
+#, no-wrap
+msgid "."
+msgstr "."
diff --git a/t/fmt/texinfoparser/macrovalue.pot b/t/fmt/texinfoparser/macrovalue.pot
new file mode 100644
index 00000000..b1ab0e51
--- /dev/null
+++ b/t/fmt/texinfoparser/macrovalue.pot
@@ -0,0 +1,76 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: @macro
+#: macrovalue.texi:2
+#, no-wrap
+msgid ""
+"@macro betweenpara {a, b}\n"
+"end of prev \\b\\.\n"
+"\n"
+"begin of next \\a\\,\n"
+"@end macro"
+msgstr ""
+
+#. type: line_arg 1 in @node
+#: macrovalue.texi:8
+#, no-wrap
+msgid "Top"
+msgstr ""
+
+#. type: line_arg 1 in @top
+#: macrovalue.texi:9
+#, no-wrap
+msgid "test macro and value"
+msgstr ""
+
+#. type: paragraph
+#: macrovalue.texi:11
+#, no-wrap
+msgid "there is @betweenpara{farg, secondarg}"
+msgstr ""
+
+#. type: paragraph
+#: macrovalue.texi:11
+#, no-wrap
+msgid " and more."
+msgstr ""
+
+#. type: paragraph
+#: macrovalue.texi:13
+#, no-wrap
+msgid ""
+"there is lot @betweenpara{before empty line\n"
+"\n"
+"after empty line\n"
+"\n"
+"@example\n"
+"in example\n"
+"\n"
+"also example\n"
+"@end example\n"
+"\n"
+", secondarg2\n"
+"}"
+msgstr ""
+
+#. type: paragraph
+#: macrovalue.texi:24
+#, no-wrap
+msgid "."
+msgstr ""
diff --git a/t/fmt/texinfoparser/macrovalue.texi b/t/fmt/texinfoparser/macrovalue.texi
new file mode 100644
index 00000000..7220df74
--- /dev/null
+++ b/t/fmt/texinfoparser/macrovalue.texi
@@ -0,0 +1,26 @@
+
+@macro betweenpara {a, b}
+end of prev \b\.
+
+begin of next \a\,
+@end macro
+
+@node Top
+@top test macro and value
+
+there is @betweenpara{farg, secondarg} and more.
+
+there is lot @betweenpara{before empty line
+
+after empty line
+
+@example
+in example
+
+also example
+@end example
+
+, secondarg2
+}.
+
+
diff --git a/t/fmt/texinfoparser/macrovalue.trans b/t/fmt/texinfoparser/macrovalue.trans
new file mode 100644
index 00000000..d032403b
--- /dev/null
+++ b/t/fmt/texinfoparser/macrovalue.trans
@@ -0,0 +1,26 @@
+
+@MACRO BETWEENPARA {A, B}
+END OF PREV \b\.
+
+BEGIN OF NEXT \a\,
+@END MACRO
+
+@node TOP
+@top TEST MACRO AND VALUE
+
+THERE IS @BETWEENPARA{FARG, SECONDARG} AND MORE.
+
+THERE IS LOT @BETWEENPARA{BEFORE EMPTY LINE
+
+AFTER EMPTY LINE
+
+@EXAMPLE
+IN EXAMPLE
+
+ALSO EXAMPLE
+@END EXAMPLE
+
+, SECONDARG2
+}.
+
+
diff --git a/t/fmt/texinfoparser/partialmenus.norm b/t/fmt/texinfoparser/partialmenus.norm
new file mode 100644
index 00000000..f8663a2b
--- /dev/null
+++ b/t/fmt/texinfoparser/partialmenus.norm
@@ -0,0 +1,14 @@
+\input texinfo
+
+@c These menus do not contain a description, which used to cause a
+@c Texinfo menu entry to not be translated.
+@menu
+* A menu entry without any description::
+* Optional menu name: The menu node::
+@end menu
+
+@node A menu entry without any description
+@chapter A menu entry without any description
+
+@node The menu node
+@chapter Optional menu name
diff --git a/t/fmt/texinfoparser/partialmenus.po b/t/fmt/texinfoparser/partialmenus.po
new file mode 100644
index 00000000..a83de2c8
--- /dev/null
+++ b/t/fmt/texinfoparser/partialmenus.po
@@ -0,0 +1,59 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @c
+#: partialmenus.texi:3
+#, no-wrap
+msgid "These menus do not contain a description, which used to cause a"
+msgstr "THESE MENUS DO NOT CONTAIN A DESCRIPTION, WHICH USED TO CAUSE A"
+
+#. type: line_arg 1 in @c
+#: partialmenus.texi:4
+#, no-wrap
+msgid "Texinfo menu entry to not be translated."
+msgstr "TEXINFO MENU ENTRY TO NOT BE TRANSLATED."
+
+#. type: menu_entry
+#: partialmenus.texi:6
+#, no-wrap
+msgid "* A menu entry without any description::"
+msgstr "* A MENU ENTRY WITHOUT ANY DESCRIPTION::"
+
+#. type: menu_entry
+#: partialmenus.texi:7
+#, no-wrap
+msgid "* Optional menu name: The menu node::"
+msgstr "* OPTIONAL MENU NAME: THE MENU NODE::"
+
+#. type: line_arg 1 in @chapter
+#: partialmenus.texi:10 partialmenus.texi:11
+#, no-wrap
+msgid "A menu entry without any description"
+msgstr "A MENU ENTRY WITHOUT ANY DESCRIPTION"
+
+#. type: line_arg 1 in @node
+#: partialmenus.texi:13
+#, no-wrap
+msgid "The menu node"
+msgstr "THE MENU NODE"
+
+#. type: line_arg 1 in @chapter
+#: partialmenus.texi:14
+#, no-wrap
+msgid "Optional menu name"
+msgstr "OPTIONAL MENU NAME"
diff --git a/t/fmt/texinfoparser/partialmenus.pot b/t/fmt/texinfoparser/partialmenus.pot
new file mode 100644
index 00000000..2d31d80f
--- /dev/null
+++ b/t/fmt/texinfoparser/partialmenus.pot
@@ -0,0 +1,59 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @c
+#: partialmenus.texi:3
+#, no-wrap
+msgid "These menus do not contain a description, which used to cause a"
+msgstr ""
+
+#. type: line_arg 1 in @c
+#: partialmenus.texi:4
+#, no-wrap
+msgid "Texinfo menu entry to not be translated."
+msgstr ""
+
+#. type: menu_entry
+#: partialmenus.texi:6
+#, no-wrap
+msgid "* A menu entry without any description::"
+msgstr ""
+
+#. type: menu_entry
+#: partialmenus.texi:7
+#, no-wrap
+msgid "* Optional menu name: The menu node::"
+msgstr ""
+
+#. type: line_arg 1 in @chapter
+#: partialmenus.texi:10 partialmenus.texi:11
+#, no-wrap
+msgid "A menu entry without any description"
+msgstr ""
+
+#. type: line_arg 1 in @node
+#: partialmenus.texi:13
+#, no-wrap
+msgid "The menu node"
+msgstr ""
+
+#. type: line_arg 1 in @chapter
+#: partialmenus.texi:14
+#, no-wrap
+msgid "Optional menu name"
+msgstr ""
diff --git a/t/fmt/texinfoparser/partialmenus.texi b/t/fmt/texinfoparser/partialmenus.texi
new file mode 100644
index 00000000..f8663a2b
--- /dev/null
+++ b/t/fmt/texinfoparser/partialmenus.texi
@@ -0,0 +1,14 @@
+\input texinfo
+
+@c These menus do not contain a description, which used to cause a
+@c Texinfo menu entry to not be translated.
+@menu
+* A menu entry without any description::
+* Optional menu name: The menu node::
+@end menu
+
+@node A menu entry without any description
+@chapter A menu entry without any description
+
+@node The menu node
+@chapter Optional menu name
diff --git a/t/fmt/texinfoparser/partialmenus.trans b/t/fmt/texinfoparser/partialmenus.trans
new file mode 100644
index 00000000..eb87abd8
--- /dev/null
+++ b/t/fmt/texinfoparser/partialmenus.trans
@@ -0,0 +1,14 @@
+\input texinfo
+
+@c THESE MENUS DO NOT CONTAIN A DESCRIPTION, WHICH USED TO CAUSE A
+@c TEXINFO MENU ENTRY TO NOT BE TRANSLATED.
+@menu
+* A MENU ENTRY WITHOUT ANY DESCRIPTION::
+* OPTIONAL MENU NAME: THE MENU NODE::
+@end menu
+
+@node A MENU ENTRY WITHOUT ANY DESCRIPTION
+@chapter A MENU ENTRY WITHOUT ANY DESCRIPTION
+
+@node THE MENU NODE
+@chapter OPTIONAL MENU NAME
diff --git a/t/fmt/texinfoparser/texifeatures.norm b/t/fmt/texinfoparser/texifeatures.norm
new file mode 100644
index 00000000..b78f94f0
--- /dev/null
+++ b/t/fmt/texinfoparser/texifeatures.norm
@@ -0,0 +1,182 @@
+\input texinfo.tex
+
+@setfilename texifeatures.info
+
+@dircategory Test of something
+
+@direntry
+* Texinfo: (texinfo).           The GNU documentation format.
+* install-info: (texinfo)Invoking install-info
+
+Something else
+@end direntry
+
+@everyheading here @thischapter @| @thispage @| @today{}
+
+@hyphenation{a b-c d
+azeezaa}
+
+Para before top.
+
+@node Top
+@top Showcase Texinfo code that could challenge the parser @comment challenge?
+
+@heading in heading heading comment after DEL
+
+ lone comment after DEL
+
+abc  comment after DEL
+more in the para. With @@ space and newline @ @
+after.  Now inline image @image{inline, ,,
+alt inline image}. 
+
+@image{image, ,,alt image, .txt}
+
+Now a footnote@footnote{We are in footnote
+
+other para
+
+@example
+in footnote
+@end example
+
+after}
+
+@itemize some text
+@item what is translted@footnote{Why not in item} in item
+
+maybe some?
+@item
+@end itemize
+
+@float Figure, type
+in float
+@caption{in caption}
+@end float
+
+@quotation normal text
+in quotation
+
+second para
+@end quotation
+
+@quotation Caution
+Quotation special DocBook tag
+@end quotation
+
+@cartouche cartouche title@comment end cartouche title comment
+in cartouche
+@end cartouche
+
+@cindex my entry @sortas{E} @subentry sub1 @sortas{S}
+
+@displaymath
+disp--laymath
+f(x) = {1 \\over \\sigma \\sqrt{2\\pi}}e@sup{-{1 \\over 2}\\left({x-\\mu \\over \\sigma}\\right)^2}
+@end displaymath
+
+Some math @math{--a {\\frac{1}{2}} @minus{}}.
+
+@math{a + b}
+
+@float Figure,other figure @comment comment on float line
+in second float
+@end float
+
+@float , only a ref
+in float only a ref
+@end float
+
+@float Only a type
+in float Only a type
+@end float
+
+@multitable {some text for column one} {for column two}
+@item some text for column one
+@tab aaa
+@end multitable
+
+@multitable @columnfractions .33 .40 .33
+@item item first abc
+
+item second
+
+@tab tab first para
+
+tab second para
+@end multitable
+
+@defvr c--ategory d--efvr_name
+d--efvr
+@end defvr
+ 
+@deffn c--ategory n--ame a--rguments...
+d--effn
+@end deffn
+
+@deftypefn c--ategory t--ype d--eftypefn_name a--rguments...
+d--eftypefn
+@end deftypefn
+
+@defun d--efun_name a--rguments...
+d--efun
+@end defun
+
+@defun d--efun_name2 a--rguments2... @comment on defun
+@end defun
+
+@deffn category deffn_name arguments @
+   more {args @
+  with end of line within} with 3 @@ @@@
+ {one last arg}
+deffn
+@end deffn
+
+@deffn fset @var{i} a g
+@c comment
+@deffnx {truc} bidulr machin...
+@end deffn
+
+@deftypevr {Global Flag} int enable @
+        (arg in brace, [something @var{in v--ar}, @b{in, b} {, comma} a@var{pref} p]) last
+@end deftypevr
+
+@defblock
+@defline Funoid foo (bar)
+description1 description1 description1 description1 description1
+description1 description1 description1 description1 description1
+@defline Funnyoid foo2 (bar2, baz2)
+description2 description2 description2 description2 description2
+
+description2 description2 description2 description2 description2
+@end defblock
+
+@defblock
+misc text inside
+@end defblock
+
+
+@node chap, Top, ochap, Top
+@chapter Chapter
+
+@node ochap
+@chapter Other Chapter
+
+@anchor{my anchor}
+
+@namedanchor{ nanchor, name of NA}
+
+Para with @anchor{in para} and @namedanchor{nanchor in para, name of NA in
+para} and more.
+
+@errormsg{Wow Not Now!}
+
+in para @errormsg{errmsg in para}.
+
+@titlefont{Could ba a title, in titlefont }.
+
+A titlefont after text, not really in paragraph @titlefont{TFont in para}.
+
+@bye @comment bye comment
+
+After bye
diff --git a/t/fmt/texinfoparser/texifeatures.norm.stderr b/t/fmt/texinfoparser/texifeatures.norm.stderr
new file mode 100644
index 00000000..f2732c3e
--- /dev/null
+++ b/t/fmt/texinfoparser/texifeatures.norm.stderr
@@ -0,0 +1,2 @@
+po4a::texinfo: texifeatures.texi:172: Wow Not Now!
+po4a::texinfo: texifeatures.texi:174: errmsg in para
diff --git a/t/fmt/texinfoparser/texifeatures.po b/t/fmt/texinfoparser/texifeatures.po
new file mode 100644
index 00000000..82b394e3
--- /dev/null
+++ b/t/fmt/texinfoparser/texifeatures.po
@@ -0,0 +1,557 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @dircategory
+#: texifeatures.texi:5
+#, no-wrap
+msgid "Test of something"
+msgstr "TEST OF SOMETHING"
+
+#. type: menu_entry
+#: texifeatures.texi:8
+#, no-wrap
+msgid "* Texinfo: (texinfo).           The GNU documentation format."
+msgstr "* TEXINFO: (TEXINFO).           THE GNU DOCUMENTATION FORMAT."
+
+#. type: menu_entry
+#: texifeatures.texi:9
+#, no-wrap
+msgid "* install-info: (texinfo)Invoking install-info"
+msgstr "* INSTALL-INFO: (TEXINFO)INVOKING INSTALL-INFO"
+
+#. type: preformatted
+#: texifeatures.texi:10
+#, no-wrap
+msgid ""
+"\n"
+"Something else"
+msgstr ""
+"\n"
+"SOMETHING ELSE"
+
+#. type: line_arg 1 in @everyheading
+#: texifeatures.texi:14
+#, no-wrap
+msgid "here @thischapter @| @thispage @| @today{}"
+msgstr "HERE @THISCHAPTER @| @THISPAGE @| @TODAY{}"
+
+#. type: @hyphenation
+#: texifeatures.texi:16
+#, no-wrap
+msgid ""
+"@hyphenation{a b-c d\n"
+"azeezaa}"
+msgstr ""
+"@HYPHENATION{A B-C D\n"
+"AZEEZAA}"
+
+#. type: paragraph
+#: texifeatures.texi:19
+#, no-wrap
+msgid "Para before top."
+msgstr "PARA BEFORE TOP."
+
+#. type: line_arg 4 in @node
+#: texifeatures.texi:21 texifeatures.texi:159
+#, no-wrap
+msgid "Top"
+msgstr "TOP"
+
+#. type: line_arg 1 in @top
+#: texifeatures.texi:22
+#, no-wrap
+msgid "Showcase Texinfo code that could challenge the parser @comment challenge?"
+msgstr "SHOWCASE TEXINFO CODE THAT COULD CHALLENGE THE PARSER @COMMENT CHALLENGE?"
+
+#. type: line_arg 1 in @heading
+#: texifeatures.texi:24
+#, no-wrap
+msgid "in heading heading comment after DEL\n"
+msgstr "IN HEADING HEADING COMMENT AFTER DEL\n"
+
+#. type: DEL comment
+#: texifeatures.texi:26
+#, no-wrap
+msgid " lone comment after DEL"
+msgstr " LONE COMMENT AFTER DEL"
+
+#. type: paragraph
+#: texifeatures.texi:28
+#, no-wrap
+msgid ""
+"abc  comment after DEL\n"
+"more in the para. With @@ space and newline @ @\n"
+"after.  Now inline image @image{inline, ,,\n"
+"alt inline image}. "
+msgstr ""
+"ABC  COMMENT AFTER DEL\n"
+"MORE IN THE PARA. WITH @@ SPACE AND NEWLINE @ @\n"
+"AFTER.  NOW INLINE IMAGE @IMAGE{INLINE, ,,\n"
+"ALT INLINE IMAGE}. "
+
+#. type: brace_arg 4 in @image
+#: texifeatures.texi:33
+#, no-wrap
+msgid "alt image"
+msgstr "ALT IMAGE"
+
+#. type: paragraph
+#: texifeatures.texi:35
+#, no-wrap
+msgid ""
+"Now a footnote@footnote{We are in footnote\n"
+"\n"
+"other para\n"
+"\n"
+"@example\n"
+"in footnote\n"
+"@end example\n"
+"\n"
+"after}"
+msgstr ""
+"NOW A FOOTNOTE@FOOTNOTE{WE ARE IN FOOTNOTE\n"
+"\n"
+"OTHER PARA\n"
+"\n"
+"@EXAMPLE\n"
+"IN FOOTNOTE\n"
+"@END EXAMPLE\n"
+"\n"
+"AFTER}"
+
+#. type: block_line_arg 1 in @itemize
+#: texifeatures.texi:45
+#, no-wrap
+msgid "some text"
+msgstr "SOME TEXT"
+
+#. type: paragraph
+#: texifeatures.texi:46
+#, no-wrap
+msgid "what is translted@footnote{Why not in item} in item"
+msgstr "WHAT IS TRANSLTED@FOOTNOTE{WHY NOT IN ITEM} IN ITEM"
+
+#. type: paragraph
+#: texifeatures.texi:48
+#, no-wrap
+msgid "maybe some?"
+msgstr "MAYBE SOME?"
+
+#. type: block_line_arg 1 in @float
+#: texifeatures.texi:52 texifeatures.texi:82
+#, no-wrap
+msgid "Figure"
+msgstr "FIGURE"
+
+#. type: block_line_arg 2 in @float
+#: texifeatures.texi:52
+#, no-wrap
+msgid "type"
+msgstr "TYPE"
+
+#. type: paragraph
+#: texifeatures.texi:53
+#, no-wrap
+msgid "in float"
+msgstr "IN FLOAT"
+
+#. type: @caption
+#: texifeatures.texi:54
+#, no-wrap
+msgid "@caption{in caption}"
+msgstr "@CAPTION{IN CAPTION}"
+
+#. type: block_line_arg 1 in @quotation
+#: texifeatures.texi:57
+#, no-wrap
+msgid "normal text"
+msgstr "NORMAL TEXT"
+
+#. type: paragraph
+#: texifeatures.texi:58
+#, no-wrap
+msgid "in quotation"
+msgstr "IN QUOTATION"
+
+#. type: paragraph
+#: texifeatures.texi:60
+#, no-wrap
+msgid "second para"
+msgstr "SECOND PARA"
+
+#. type: block_line_arg 1 in @quotation
+#: texifeatures.texi:63
+#, no-wrap
+msgid "Caution"
+msgstr "CAUTION"
+
+#. type: paragraph
+#: texifeatures.texi:64
+#, no-wrap
+msgid "Quotation special DocBook tag"
+msgstr "QUOTATION SPECIAL DOCBOOK TAG"
+
+#. type: block_line_arg 1 in @cartouche
+#: texifeatures.texi:67
+#, no-wrap
+msgid "cartouche title@comment end cartouche title comment"
+msgstr "CARTOUCHE TITLE@COMMENT END CARTOUCHE TITLE COMMENT"
+
+#. type: paragraph
+#: texifeatures.texi:68
+#, no-wrap
+msgid "in cartouche"
+msgstr "IN CARTOUCHE"
+
+#. type: line_arg 1 in @cindex
+#: texifeatures.texi:71
+#, no-wrap
+msgid "my entry @sortas{E} @subentry sub1 @sortas{S}"
+msgstr "MY ENTRY @SORTAS{E} @SUBENTRY SUB1 @SORTAS{S}"
+
+#. type: @displaymath
+#: texifeatures.texi:73
+#, no-wrap
+msgid ""
+"@displaymath\n"
+"disp--laymath\n"
+"f(x) = {1 \\\\over \\\\sigma \\\\sqrt{2\\\\pi}}e@sup{-{1 \\\\over "
+"2}\\\\left({x-\\\\mu \\\\over \\\\sigma}\\\\right)^2}\n"
+"@end displaymath"
+msgstr ""
+"@DISPLAYMATH\n"
+"DISP--LAYMATH\n"
+"F(X) = {1 \\\\oVER \\\\sIGMA \\\\sQRT{2\\\\pI}}E@SUP{-{1 \\\\oVER "
+"2}\\\\lEFT({X-\\\\mU \\\\oVER \\\\sIGMA}\\\\rIGHT)^2}\n"
+"@END DISPLAYMATH"
+
+#. type: paragraph
+#: texifeatures.texi:78
+#, no-wrap
+msgid "Some math @math{--a {\\\\frac{1}{2}} @minus{}}."
+msgstr "SOME MATH @MATH{--A {\\\\fRAC{1}{2}} @MINUS{}}."
+
+#. type: paragraph
+#: texifeatures.texi:80
+#, no-wrap
+msgid "@math{a + b}"
+msgstr "@MATH{A + B}"
+
+#. type: block_line_arg 2 in @float
+#: texifeatures.texi:82
+#, no-wrap
+msgid "other figure @comment comment on float line"
+msgstr "OTHER FIGURE @COMMENT COMMENT ON FLOAT LINE"
+
+#. type: paragraph
+#: texifeatures.texi:83
+#, no-wrap
+msgid "in second float"
+msgstr "IN SECOND FLOAT"
+
+#. type: block_line_arg 2 in @float
+#: texifeatures.texi:86
+#, no-wrap
+msgid "only a ref"
+msgstr "ONLY A REF"
+
+#. type: paragraph
+#: texifeatures.texi:87
+#, no-wrap
+msgid "in float only a ref"
+msgstr "IN FLOAT ONLY A REF"
+
+#. type: block_line_arg 1 in @float
+#: texifeatures.texi:90
+#, no-wrap
+msgid "Only a type"
+msgstr "ONLY A TYPE"
+
+#. type: paragraph
+#: texifeatures.texi:91
+#, no-wrap
+msgid "in float Only a type"
+msgstr "IN FLOAT ONLY A TYPE"
+
+#. type: block_line_arg 1 in @multitable
+#: texifeatures.texi:94
+#, no-wrap
+msgid "{some text for column one} {for column two}"
+msgstr "{SOME TEXT FOR COLUMN ONE} {FOR COLUMN TWO}"
+
+#. type: paragraph
+#: texifeatures.texi:95
+#, no-wrap
+msgid "some text for column one"
+msgstr "SOME TEXT FOR COLUMN ONE"
+
+#. type: paragraph
+#: texifeatures.texi:96
+#, no-wrap
+msgid "aaa"
+msgstr "AAA"
+
+#. type: paragraph
+#: texifeatures.texi:100
+#, no-wrap
+msgid "item first abc"
+msgstr "ITEM FIRST ABC"
+
+#. type: paragraph
+#: texifeatures.texi:102
+#, no-wrap
+msgid "item second"
+msgstr "ITEM SECOND"
+
+#. type: paragraph
+#: texifeatures.texi:104
+#, no-wrap
+msgid "tab first para"
+msgstr "TAB FIRST PARA"
+
+#. type: paragraph
+#: texifeatures.texi:106
+#, no-wrap
+msgid "tab second para"
+msgstr "TAB SECOND PARA"
+
+#. type: block_line_arg 1 in @defvr
+#: texifeatures.texi:109
+#, no-wrap
+msgid "c--ategory d--efvr_name"
+msgstr "C--ATEGORY D--EFVR_NAME"
+
+#. type: paragraph
+#: texifeatures.texi:110
+#, no-wrap
+msgid "d--efvr"
+msgstr "D--EFVR"
+
+#. type: block_line_arg 1 in @deffn
+#: texifeatures.texi:113
+#, no-wrap
+msgid "c--ategory n--ame a--rguments..."
+msgstr "C--ATEGORY N--AME A--RGUMENTS..."
+
+#. type: paragraph
+#: texifeatures.texi:114
+#, no-wrap
+msgid "d--effn"
+msgstr "D--EFFN"
+
+#. type: block_line_arg 1 in @deftypefn
+#: texifeatures.texi:117
+#, no-wrap
+msgid "c--ategory t--ype d--eftypefn_name a--rguments..."
+msgstr "C--ATEGORY T--YPE D--EFTYPEFN_NAME A--RGUMENTS..."
+
+#. type: paragraph
+#: texifeatures.texi:118
+#, no-wrap
+msgid "d--eftypefn"
+msgstr "D--EFTYPEFN"
+
+#. type: block_line_arg 1 in @defun
+#: texifeatures.texi:121
+#, no-wrap
+msgid "d--efun_name a--rguments..."
+msgstr "D--EFUN_NAME A--RGUMENTS..."
+
+#. type: paragraph
+#: texifeatures.texi:122
+#, no-wrap
+msgid "d--efun"
+msgstr "D--EFUN"
+
+#. type: block_line_arg 1 in @defun
+#: texifeatures.texi:125
+#, no-wrap
+msgid "d--efun_name2 a--rguments2... @comment on defun"
+msgstr "D--EFUN_NAME2 A--RGUMENTS2... @COMMENT ON DEFUN"
+
+#. type: block_line_arg 1 in @deffn
+#: texifeatures.texi:128
+#, no-wrap
+msgid ""
+"category deffn_name arguments @\n"
+"   more {args @\n"
+"  with end of line within} with 3 @@ @@@\n"
+" {one last arg}"
+msgstr ""
+"CATEGORY DEFFN_NAME ARGUMENTS @\n"
+"   MORE {ARGS @\n"
+"  WITH END OF LINE WITHIN} WITH 3 @@ @@@\n"
+" {ONE LAST ARG}"
+
+#. type: paragraph
+#: texifeatures.texi:132
+#, no-wrap
+msgid "deffn"
+msgstr "DEFFN"
+
+#. type: block_line_arg 1 in @deffn
+#: texifeatures.texi:135
+#, no-wrap
+msgid "fset @var{i} a g"
+msgstr "FSET @VAR{I} A G"
+
+#. type: line_arg 1 in @c
+#: texifeatures.texi:136
+#, no-wrap
+msgid "comment"
+msgstr "COMMENT"
+
+#. type: line_arg 1 in @deffnx
+#: texifeatures.texi:137
+#, no-wrap
+msgid "{truc} bidulr machin..."
+msgstr "{TRUC} BIDULR MACHIN..."
+
+#. type: block_line_arg 1 in @deftypevr
+#: texifeatures.texi:140
+#, no-wrap
+msgid ""
+"{Global Flag} int enable @\n"
+"        (arg in brace, [something @var{in v--ar}, @b{in, b} {, comma} "
+"a@var{pref} p]) last"
+msgstr ""
+"{GLOBAL FLAG} INT ENABLE @\n"
+"        (ARG IN BRACE, [SOMETHING @VAR{IN V--AR}, @B{IN, B} {, COMMA} "
+"A@VAR{PREF} P]) LAST"
+
+#. type: line_arg 1 in @defline
+#: texifeatures.texi:145
+#, no-wrap
+msgid "Funoid foo (bar)"
+msgstr "FUNOID FOO (BAR)"
+
+#. type: paragraph
+#: texifeatures.texi:146
+#, no-wrap
+msgid ""
+"description1 description1 description1 description1 description1\n"
+"description1 description1 description1 description1 description1"
+msgstr ""
+"DESCRIPTION1 DESCRIPTION1 DESCRIPTION1 DESCRIPTION1 DESCRIPTION1\n"
+"DESCRIPTION1 DESCRIPTION1 DESCRIPTION1 DESCRIPTION1 DESCRIPTION1"
+
+#. type: line_arg 1 in @defline
+#: texifeatures.texi:148
+#, no-wrap
+msgid "Funnyoid foo2 (bar2, baz2)"
+msgstr "FUNNYOID FOO2 (BAR2, BAZ2)"
+
+#. type: paragraph
+#: texifeatures.texi:149 texifeatures.texi:151
+#, no-wrap
+msgid "description2 description2 description2 description2 description2"
+msgstr "DESCRIPTION2 DESCRIPTION2 DESCRIPTION2 DESCRIPTION2 DESCRIPTION2"
+
+#. type: paragraph
+#: texifeatures.texi:155
+#, no-wrap
+msgid "misc text inside"
+msgstr "MISC TEXT INSIDE"
+
+#. type: line_arg 1 in @node
+#: texifeatures.texi:159
+#, no-wrap
+msgid "chap"
+msgstr "CHAP"
+
+#. type: line_arg 1 in @node
+#: texifeatures.texi:159 texifeatures.texi:162
+#, no-wrap
+msgid "ochap"
+msgstr "OCHAP"
+
+#. type: line_arg 1 in @chapter
+#: texifeatures.texi:160
+#, no-wrap
+msgid "Chapter"
+msgstr "CHAPTER"
+
+#. type: line_arg 1 in @chapter
+#: texifeatures.texi:163
+#, no-wrap
+msgid "Other Chapter"
+msgstr "OTHER CHAPTER"
+
+#. type: @anchor
+#: texifeatures.texi:165
+#, no-wrap
+msgid "@anchor{my anchor}"
+msgstr "@ANCHOR{MY ANCHOR}"
+
+#. type: @namedanchor
+#: texifeatures.texi:167
+#, no-wrap
+msgid "@namedanchor{ nanchor, name of NA}"
+msgstr "@NAMEDANCHOR{ NANCHOR, NAME OF NA}"
+
+#. type: paragraph
+#: texifeatures.texi:169
+#, no-wrap
+msgid ""
+"Para with @anchor{in para} and @namedanchor{nanchor in para, name of NA in\n"
+"para} and more."
+msgstr ""
+"PARA WITH @ANCHOR{IN PARA} AND @NAMEDANCHOR{NANCHOR IN PARA, NAME OF NA IN\n"
+"PARA} AND MORE."
+
+#. type: @errormsg
+#: texifeatures.texi:172
+#, no-wrap
+msgid "@errormsg{Wow Not Now!}"
+msgstr "@ERRORMSG{WOW NOT NOW!}"
+
+#. type: paragraph
+#: texifeatures.texi:174
+#, no-wrap
+msgid "in para @errormsg{errmsg in para}."
+msgstr "IN PARA @ERRORMSG{ERRMSG IN PARA}."
+
+#. type: @titlefont
+#: texifeatures.texi:176
+#, no-wrap
+msgid "@titlefont{Could ba a title, in titlefont }"
+msgstr "@TITLEFONT{COULD BA A TITLE, IN TITLEFONT }"
+
+#. type: paragraph
+#: texifeatures.texi:176 texifeatures.texi:178
+#, no-wrap
+msgid "."
+msgstr "."
+
+#. type: paragraph
+#: texifeatures.texi:178
+#, no-wrap
+msgid "A titlefont after text, not really in paragraph "
+msgstr "A TITLEFONT AFTER TEXT, NOT REALLY IN PARAGRAPH "
+
+#. type: @titlefont
+#: texifeatures.texi:178
+#, no-wrap
+msgid "@titlefont{TFont in para}"
+msgstr "@TITLEFONT{TFONT IN PARA}"
+
+#. type: line_arg 1 in @comment
+#: texifeatures.texi:180
+#, no-wrap
+msgid "bye comment"
+msgstr "BYE COMMENT"
diff --git a/t/fmt/texinfoparser/texifeatures.pot b/t/fmt/texinfoparser/texifeatures.pot
new file mode 100644
index 00000000..fdc6dd0d
--- /dev/null
+++ b/t/fmt/texinfoparser/texifeatures.pot
@@ -0,0 +1,524 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @dircategory
+#: texifeatures.texi:5
+#, no-wrap
+msgid "Test of something"
+msgstr ""
+
+#. type: menu_entry
+#: texifeatures.texi:8
+#, no-wrap
+msgid "* Texinfo: (texinfo).           The GNU documentation format."
+msgstr ""
+
+#. type: menu_entry
+#: texifeatures.texi:9
+#, no-wrap
+msgid "* install-info: (texinfo)Invoking install-info"
+msgstr ""
+
+#. type: preformatted
+#: texifeatures.texi:10
+#, no-wrap
+msgid ""
+"\n"
+"Something else"
+msgstr ""
+
+#. type: line_arg 1 in @everyheading
+#: texifeatures.texi:14
+#, no-wrap
+msgid "here @thischapter @| @thispage @| @today{}"
+msgstr ""
+
+#. type: @hyphenation
+#: texifeatures.texi:16
+#, no-wrap
+msgid ""
+"@hyphenation{a b-c d\n"
+"azeezaa}"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:19
+#, no-wrap
+msgid "Para before top."
+msgstr ""
+
+#. type: line_arg 4 in @node
+#: texifeatures.texi:21 texifeatures.texi:159
+#, no-wrap
+msgid "Top"
+msgstr ""
+
+#. type: line_arg 1 in @top
+#: texifeatures.texi:22
+#, no-wrap
+msgid "Showcase Texinfo code that could challenge the parser @comment challenge?"
+msgstr ""
+
+#. type: line_arg 1 in @heading
+#: texifeatures.texi:24
+#, no-wrap
+msgid "in heading heading comment after DEL\n"
+msgstr ""
+
+#. type: DEL comment
+#: texifeatures.texi:26
+#, no-wrap
+msgid " lone comment after DEL"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:28
+#, no-wrap
+msgid ""
+"abc  comment after DEL\n"
+"more in the para. With @@ space and newline @ @\n"
+"after.  Now inline image @image{inline, ,,\n"
+"alt inline image}. "
+msgstr ""
+
+#. type: brace_arg 4 in @image
+#: texifeatures.texi:33
+#, no-wrap
+msgid "alt image"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:35
+#, no-wrap
+msgid ""
+"Now a footnote@footnote{We are in footnote\n"
+"\n"
+"other para\n"
+"\n"
+"@example\n"
+"in footnote\n"
+"@end example\n"
+"\n"
+"after}"
+msgstr ""
+
+#. type: block_line_arg 1 in @itemize
+#: texifeatures.texi:45
+#, no-wrap
+msgid "some text"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:46
+#, no-wrap
+msgid "what is translted@footnote{Why not in item} in item"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:48
+#, no-wrap
+msgid "maybe some?"
+msgstr ""
+
+#. type: block_line_arg 1 in @float
+#: texifeatures.texi:52 texifeatures.texi:82
+#, no-wrap
+msgid "Figure"
+msgstr ""
+
+#. type: block_line_arg 2 in @float
+#: texifeatures.texi:52
+#, no-wrap
+msgid "type"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:53
+#, no-wrap
+msgid "in float"
+msgstr ""
+
+#. type: @caption
+#: texifeatures.texi:54
+#, no-wrap
+msgid "@caption{in caption}"
+msgstr ""
+
+#. type: block_line_arg 1 in @quotation
+#: texifeatures.texi:57
+#, no-wrap
+msgid "normal text"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:58
+#, no-wrap
+msgid "in quotation"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:60
+#, no-wrap
+msgid "second para"
+msgstr ""
+
+#. type: block_line_arg 1 in @quotation
+#: texifeatures.texi:63
+#, no-wrap
+msgid "Caution"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:64
+#, no-wrap
+msgid "Quotation special DocBook tag"
+msgstr ""
+
+#. type: block_line_arg 1 in @cartouche
+#: texifeatures.texi:67
+#, no-wrap
+msgid "cartouche title@comment end cartouche title comment"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:68
+#, no-wrap
+msgid "in cartouche"
+msgstr ""
+
+#. type: line_arg 1 in @cindex
+#: texifeatures.texi:71
+#, no-wrap
+msgid "my entry @sortas{E} @subentry sub1 @sortas{S}"
+msgstr ""
+
+#. type: @displaymath
+#: texifeatures.texi:73
+#, no-wrap
+msgid ""
+"@displaymath\n"
+"disp--laymath\n"
+"f(x) = {1 \\\\over \\\\sigma \\\\sqrt{2\\\\pi}}e@sup{-{1 \\\\over "
+"2}\\\\left({x-\\\\mu \\\\over \\\\sigma}\\\\right)^2}\n"
+"@end displaymath"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:78
+#, no-wrap
+msgid "Some math @math{--a {\\\\frac{1}{2}} @minus{}}."
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:80
+#, no-wrap
+msgid "@math{a + b}"
+msgstr ""
+
+#. type: block_line_arg 2 in @float
+#: texifeatures.texi:82
+#, no-wrap
+msgid "other figure @comment comment on float line"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:83
+#, no-wrap
+msgid "in second float"
+msgstr ""
+
+#. type: block_line_arg 2 in @float
+#: texifeatures.texi:86
+#, no-wrap
+msgid "only a ref"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:87
+#, no-wrap
+msgid "in float only a ref"
+msgstr ""
+
+#. type: block_line_arg 1 in @float
+#: texifeatures.texi:90
+#, no-wrap
+msgid "Only a type"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:91
+#, no-wrap
+msgid "in float Only a type"
+msgstr ""
+
+#. type: block_line_arg 1 in @multitable
+#: texifeatures.texi:94
+#, no-wrap
+msgid "{some text for column one} {for column two}"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:95
+#, no-wrap
+msgid "some text for column one"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:96
+#, no-wrap
+msgid "aaa"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:100
+#, no-wrap
+msgid "item first abc"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:102
+#, no-wrap
+msgid "item second"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:104
+#, no-wrap
+msgid "tab first para"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:106
+#, no-wrap
+msgid "tab second para"
+msgstr ""
+
+#. type: block_line_arg 1 in @defvr
+#: texifeatures.texi:109
+#, no-wrap
+msgid "c--ategory d--efvr_name"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:110
+#, no-wrap
+msgid "d--efvr"
+msgstr ""
+
+#. type: block_line_arg 1 in @deffn
+#: texifeatures.texi:113
+#, no-wrap
+msgid "c--ategory n--ame a--rguments..."
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:114
+#, no-wrap
+msgid "d--effn"
+msgstr ""
+
+#. type: block_line_arg 1 in @deftypefn
+#: texifeatures.texi:117
+#, no-wrap
+msgid "c--ategory t--ype d--eftypefn_name a--rguments..."
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:118
+#, no-wrap
+msgid "d--eftypefn"
+msgstr ""
+
+#. type: block_line_arg 1 in @defun
+#: texifeatures.texi:121
+#, no-wrap
+msgid "d--efun_name a--rguments..."
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:122
+#, no-wrap
+msgid "d--efun"
+msgstr ""
+
+#. type: block_line_arg 1 in @defun
+#: texifeatures.texi:125
+#, no-wrap
+msgid "d--efun_name2 a--rguments2... @comment on defun"
+msgstr ""
+
+#. type: block_line_arg 1 in @deffn
+#: texifeatures.texi:128
+#, no-wrap
+msgid ""
+"category deffn_name arguments @\n"
+"   more {args @\n"
+"  with end of line within} with 3 @@ @@@\n"
+" {one last arg}"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:132
+#, no-wrap
+msgid "deffn"
+msgstr ""
+
+#. type: block_line_arg 1 in @deffn
+#: texifeatures.texi:135
+#, no-wrap
+msgid "fset @var{i} a g"
+msgstr ""
+
+#. type: line_arg 1 in @c
+#: texifeatures.texi:136
+#, no-wrap
+msgid "comment"
+msgstr ""
+
+#. type: line_arg 1 in @deffnx
+#: texifeatures.texi:137
+#, no-wrap
+msgid "{truc} bidulr machin..."
+msgstr ""
+
+#. type: block_line_arg 1 in @deftypevr
+#: texifeatures.texi:140
+#, no-wrap
+msgid ""
+"{Global Flag} int enable @\n"
+"        (arg in brace, [something @var{in v--ar}, @b{in, b} {, comma} "
+"a@var{pref} p]) last"
+msgstr ""
+
+#. type: line_arg 1 in @defline
+#: texifeatures.texi:145
+#, no-wrap
+msgid "Funoid foo (bar)"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:146
+#, no-wrap
+msgid ""
+"description1 description1 description1 description1 description1\n"
+"description1 description1 description1 description1 description1"
+msgstr ""
+
+#. type: line_arg 1 in @defline
+#: texifeatures.texi:148
+#, no-wrap
+msgid "Funnyoid foo2 (bar2, baz2)"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:149 texifeatures.texi:151
+#, no-wrap
+msgid "description2 description2 description2 description2 description2"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:155
+#, no-wrap
+msgid "misc text inside"
+msgstr ""
+
+#. type: line_arg 1 in @node
+#: texifeatures.texi:159
+#, no-wrap
+msgid "chap"
+msgstr ""
+
+#. type: line_arg 1 in @node
+#: texifeatures.texi:159 texifeatures.texi:162
+#, no-wrap
+msgid "ochap"
+msgstr ""
+
+#. type: line_arg 1 in @chapter
+#: texifeatures.texi:160
+#, no-wrap
+msgid "Chapter"
+msgstr ""
+
+#. type: line_arg 1 in @chapter
+#: texifeatures.texi:163
+#, no-wrap
+msgid "Other Chapter"
+msgstr ""
+
+#. type: @anchor
+#: texifeatures.texi:165
+#, no-wrap
+msgid "@anchor{my anchor}"
+msgstr ""
+
+#. type: @namedanchor
+#: texifeatures.texi:167
+#, no-wrap
+msgid "@namedanchor{ nanchor, name of NA}"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:169
+#, no-wrap
+msgid ""
+"Para with @anchor{in para} and @namedanchor{nanchor in para, name of NA in\n"
+"para} and more."
+msgstr ""
+
+#. type: @errormsg
+#: texifeatures.texi:172
+#, no-wrap
+msgid "@errormsg{Wow Not Now!}"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:174
+#, no-wrap
+msgid "in para @errormsg{errmsg in para}."
+msgstr ""
+
+#. type: @titlefont
+#: texifeatures.texi:176
+#, no-wrap
+msgid "@titlefont{Could ba a title, in titlefont }"
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:176 texifeatures.texi:178
+#, no-wrap
+msgid "."
+msgstr ""
+
+#. type: paragraph
+#: texifeatures.texi:178
+#, no-wrap
+msgid "A titlefont after text, not really in paragraph "
+msgstr ""
+
+#. type: @titlefont
+#: texifeatures.texi:178
+#, no-wrap
+msgid "@titlefont{TFont in para}"
+msgstr ""
+
+#. type: line_arg 1 in @comment
+#: texifeatures.texi:180
+#, no-wrap
+msgid "bye comment"
+msgstr ""
diff --git a/t/fmt/texinfoparser/texifeatures.texi b/t/fmt/texinfoparser/texifeatures.texi
new file mode 100644
index 00000000..b78f94f0
--- /dev/null
+++ b/t/fmt/texinfoparser/texifeatures.texi
@@ -0,0 +1,182 @@
+\input texinfo.tex
+
+@setfilename texifeatures.info
+
+@dircategory Test of something
+
+@direntry
+* Texinfo: (texinfo).           The GNU documentation format.
+* install-info: (texinfo)Invoking install-info
+
+Something else
+@end direntry
+
+@everyheading here @thischapter @| @thispage @| @today{}
+
+@hyphenation{a b-c d
+azeezaa}
+
+Para before top.
+
+@node Top
+@top Showcase Texinfo code that could challenge the parser @comment challenge?
+
+@heading in heading heading comment after DEL
+
+ lone comment after DEL
+
+abc  comment after DEL
+more in the para. With @@ space and newline @ @
+after.  Now inline image @image{inline, ,,
+alt inline image}. 
+
+@image{image, ,,alt image, .txt}
+
+Now a footnote@footnote{We are in footnote
+
+other para
+
+@example
+in footnote
+@end example
+
+after}
+
+@itemize some text
+@item what is translted@footnote{Why not in item} in item
+
+maybe some?
+@item
+@end itemize
+
+@float Figure, type
+in float
+@caption{in caption}
+@end float
+
+@quotation normal text
+in quotation
+
+second para
+@end quotation
+
+@quotation Caution
+Quotation special DocBook tag
+@end quotation
+
+@cartouche cartouche title@comment end cartouche title comment
+in cartouche
+@end cartouche
+
+@cindex my entry @sortas{E} @subentry sub1 @sortas{S}
+
+@displaymath
+disp--laymath
+f(x) = {1 \\over \\sigma \\sqrt{2\\pi}}e@sup{-{1 \\over 2}\\left({x-\\mu \\over \\sigma}\\right)^2}
+@end displaymath
+
+Some math @math{--a {\\frac{1}{2}} @minus{}}.
+
+@math{a + b}
+
+@float Figure,other figure @comment comment on float line
+in second float
+@end float
+
+@float , only a ref
+in float only a ref
+@end float
+
+@float Only a type
+in float Only a type
+@end float
+
+@multitable {some text for column one} {for column two}
+@item some text for column one
+@tab aaa
+@end multitable
+
+@multitable @columnfractions .33 .40 .33
+@item item first abc
+
+item second
+
+@tab tab first para
+
+tab second para
+@end multitable
+
+@defvr c--ategory d--efvr_name
+d--efvr
+@end defvr
+ 
+@deffn c--ategory n--ame a--rguments...
+d--effn
+@end deffn
+
+@deftypefn c--ategory t--ype d--eftypefn_name a--rguments...
+d--eftypefn
+@end deftypefn
+
+@defun d--efun_name a--rguments...
+d--efun
+@end defun
+
+@defun d--efun_name2 a--rguments2... @comment on defun
+@end defun
+
+@deffn category deffn_name arguments @
+   more {args @
+  with end of line within} with 3 @@ @@@
+ {one last arg}
+deffn
+@end deffn
+
+@deffn fset @var{i} a g
+@c comment
+@deffnx {truc} bidulr machin...
+@end deffn
+
+@deftypevr {Global Flag} int enable @
+        (arg in brace, [something @var{in v--ar}, @b{in, b} {, comma} a@var{pref} p]) last
+@end deftypevr
+
+@defblock
+@defline Funoid foo (bar)
+description1 description1 description1 description1 description1
+description1 description1 description1 description1 description1
+@defline Funnyoid foo2 (bar2, baz2)
+description2 description2 description2 description2 description2
+
+description2 description2 description2 description2 description2
+@end defblock
+
+@defblock
+misc text inside
+@end defblock
+
+
+@node chap, Top, ochap, Top
+@chapter Chapter
+
+@node ochap
+@chapter Other Chapter
+
+@anchor{my anchor}
+
+@namedanchor{ nanchor, name of NA}
+
+Para with @anchor{in para} and @namedanchor{nanchor in para, name of NA in
+para} and more.
+
+@errormsg{Wow Not Now!}
+
+in para @errormsg{errmsg in para}.
+
+@titlefont{Could ba a title, in titlefont }.
+
+A titlefont after text, not really in paragraph @titlefont{TFont in para}.
+
+@bye @comment bye comment
+
+After bye
diff --git a/t/fmt/texinfoparser/texifeatures.trans b/t/fmt/texinfoparser/texifeatures.trans
new file mode 100644
index 00000000..30cc0590
--- /dev/null
+++ b/t/fmt/texinfoparser/texifeatures.trans
@@ -0,0 +1,182 @@
+\input texinfo.tex
+
+@setfilename texifeatures.info
+
+@dircategory TEST OF SOMETHING
+
+@direntry
+* TEXINFO: (TEXINFO).           THE GNU DOCUMENTATION FORMAT.
+* INSTALL-INFO: (TEXINFO)INVOKING INSTALL-INFO
+
+SOMETHING ELSE
+@end direntry
+
+@everyheading HERE @THISCHAPTER @| @THISPAGE @| @TODAY{}
+
+@HYPHENATION{A B-C D
+AZEEZAA}
+
+PARA BEFORE TOP.
+
+@node TOP
+@top SHOWCASE TEXINFO CODE THAT COULD CHALLENGE THE PARSER @COMMENT CHALLENGE?
+
+@heading IN HEADING HEADING COMMENT AFTER DEL
+
+ LONE COMMENT AFTER DEL
+
+ABC  COMMENT AFTER DEL
+MORE IN THE PARA. WITH @@ SPACE AND NEWLINE @ @
+AFTER.  NOW INLINE IMAGE @IMAGE{INLINE, ,,
+ALT INLINE IMAGE}. 
+
+@image{image, ,,ALT IMAGE, .txt}
+
+NOW A FOOTNOTE@FOOTNOTE{WE ARE IN FOOTNOTE
+
+OTHER PARA
+
+@EXAMPLE
+IN FOOTNOTE
+@END EXAMPLE
+
+AFTER}
+
+@itemize SOME TEXT
+@item WHAT IS TRANSLTED@FOOTNOTE{WHY NOT IN ITEM} IN ITEM
+
+MAYBE SOME?
+@item
+@end itemize
+
+@float FIGURE, TYPE
+IN FLOAT
+@CAPTION{IN CAPTION}
+@end float
+
+@quotation NORMAL TEXT
+IN QUOTATION
+
+SECOND PARA
+@end quotation
+
+@quotation CAUTION
+QUOTATION SPECIAL DOCBOOK TAG
+@end quotation
+
+@cartouche CARTOUCHE TITLE@COMMENT END CARTOUCHE TITLE COMMENT
+IN CARTOUCHE
+@end cartouche
+
+@cindex MY ENTRY @SORTAS{E} @SUBENTRY SUB1 @SORTAS{S}
+
+@DISPLAYMATH
+DISP--LAYMATH
+F(X) = {1 \\oVER \\sIGMA \\sQRT{2\\pI}}E@SUP{-{1 \\oVER 2}\\lEFT({X-\\mU \\oVER \\sIGMA}\\rIGHT)^2}
+@END DISPLAYMATH
+
+SOME MATH @MATH{--A {\\fRAC{1}{2}} @MINUS{}}.
+
+@MATH{A + B}
+
+@float FIGURE,OTHER FIGURE @COMMENT COMMENT ON FLOAT LINE
+IN SECOND FLOAT
+@end float
+
+@float , ONLY A REF
+IN FLOAT ONLY A REF
+@end float
+
+@float ONLY A TYPE
+IN FLOAT ONLY A TYPE
+@end float
+
+@multitable {SOME TEXT FOR COLUMN ONE} {FOR COLUMN TWO}
+@item SOME TEXT FOR COLUMN ONE
+@tab AAA
+@end multitable
+
+@multitable @columnfractions .33 .40 .33
+@item ITEM FIRST ABC
+
+ITEM SECOND
+
+@tab TAB FIRST PARA
+
+TAB SECOND PARA
+@end multitable
+
+@defvr C--ATEGORY D--EFVR_NAME
+D--EFVR
+@end defvr
+ 
+@deffn C--ATEGORY N--AME A--RGUMENTS...
+D--EFFN
+@end deffn
+
+@deftypefn C--ATEGORY T--YPE D--EFTYPEFN_NAME A--RGUMENTS...
+D--EFTYPEFN
+@end deftypefn
+
+@defun D--EFUN_NAME A--RGUMENTS...
+D--EFUN
+@end defun
+
+@defun D--EFUN_NAME2 A--RGUMENTS2... @COMMENT ON DEFUN
+@end defun
+
+@deffn CATEGORY DEFFN_NAME ARGUMENTS @
+   MORE {ARGS @
+  WITH END OF LINE WITHIN} WITH 3 @@ @@@
+ {ONE LAST ARG}
+DEFFN
+@end deffn
+
+@deffn FSET @VAR{I} A G
+@c COMMENT
+@deffnx {TRUC} BIDULR MACHIN...
+@end deffn
+
+@deftypevr {GLOBAL FLAG} INT ENABLE @
+        (ARG IN BRACE, [SOMETHING @VAR{IN V--AR}, @B{IN, B} {, COMMA} A@VAR{PREF} P]) LAST
+@end deftypevr
+
+@defblock
+@defline FUNOID FOO (BAR)
+DESCRIPTION1 DESCRIPTION1 DESCRIPTION1 DESCRIPTION1 DESCRIPTION1
+DESCRIPTION1 DESCRIPTION1 DESCRIPTION1 DESCRIPTION1 DESCRIPTION1
+@defline FUNNYOID FOO2 (BAR2, BAZ2)
+DESCRIPTION2 DESCRIPTION2 DESCRIPTION2 DESCRIPTION2 DESCRIPTION2
+
+DESCRIPTION2 DESCRIPTION2 DESCRIPTION2 DESCRIPTION2 DESCRIPTION2
+@end defblock
+
+@defblock
+MISC TEXT INSIDE
+@end defblock
+
+
+@node CHAP, TOP, OCHAP, TOP
+@chapter CHAPTER
+
+@node OCHAP
+@chapter OTHER CHAPTER
+
+@ANCHOR{MY ANCHOR}
+
+@NAMEDANCHOR{ NANCHOR, NAME OF NA}
+
+PARA WITH @ANCHOR{IN PARA} AND @NAMEDANCHOR{NANCHOR IN PARA, NAME OF NA IN
+PARA} AND MORE.
+
+@ERRORMSG{WOW NOT NOW!}
+
+IN PARA @ERRORMSG{ERRMSG IN PARA}.
+
+@TITLEFONT{COULD BA A TITLE, IN TITLEFONT }.
+
+A TITLEFONT AFTER TEXT, NOT REALLY IN PARAGRAPH @TITLEFONT{TFONT IN PARA}.
+
+@bye @comment BYE COMMENT
+
+After bye
diff --git a/t/fmt/texinfoparser/texifeatures.trans.stderr b/t/fmt/texinfoparser/texifeatures.trans.stderr
new file mode 100644
index 00000000..f2732c3e
--- /dev/null
+++ b/t/fmt/texinfoparser/texifeatures.trans.stderr
@@ -0,0 +1,2 @@
+po4a::texinfo: texifeatures.texi:172: Wow Not Now!
+po4a::texinfo: texifeatures.texi:174: errmsg in para
diff --git a/t/fmt/texinfoparser/tindex.norm b/t/fmt/texinfoparser/tindex.norm
new file mode 100644
index 00000000..be47e18e
--- /dev/null
+++ b/t/fmt/texinfoparser/tindex.norm
@@ -0,0 +1,9 @@
+\input texinfo
+
+@cindex parameters in python
+@cindex python parameters
+@documentencoding UTF-8
+@documentlanguage en
+@tindex gdb.Parameter
+@tindex Parameter
+You can implement new @value{GDBN} parameters using Python.
diff --git a/t/fmt/texinfoparser/tindex.norm.stderr b/t/fmt/texinfoparser/tindex.norm.stderr
new file mode 100644
index 00000000..81aa451d
--- /dev/null
+++ b/t/fmt/texinfoparser/tindex.norm.stderr
@@ -0,0 +1,5 @@
+po4a::texinfo: tindex.texi:3: warning: entry for index `cp' outside of any node
+po4a::texinfo: tindex.texi:4: warning: entry for index `cp' outside of any node
+po4a::texinfo: tindex.texi:7: warning: entry for index `tp' outside of any node
+po4a::texinfo: tindex.texi:8: warning: entry for index `tp' outside of any node
+po4a::texinfo: tindex.texi:9: warning: undefined flag: GDBN
diff --git a/t/fmt/texinfoparser/tindex.po b/t/fmt/texinfoparser/tindex.po
new file mode 100644
index 00000000..7b05fba4
--- /dev/null
+++ b/t/fmt/texinfoparser/tindex.po
@@ -0,0 +1,47 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @cindex
+#: tindex.texi:3
+#, no-wrap
+msgid "parameters in python"
+msgstr "PARAMETERS IN PYTHON"
+
+#. type: line_arg 1 in @cindex
+#: tindex.texi:4
+#, no-wrap
+msgid "python parameters"
+msgstr "PYTHON PARAMETERS"
+
+#. type: line_arg 1 in @tindex
+#: tindex.texi:7
+#, no-wrap
+msgid "gdb.Parameter"
+msgstr "GDB.PARAMETER"
+
+#. type: line_arg 1 in @tindex
+#: tindex.texi:8
+#, no-wrap
+msgid "Parameter"
+msgstr "PARAMETER"
+
+#. type: paragraph
+#: tindex.texi:9
+#, no-wrap
+msgid "You can implement new @value{GDBN} parameters using Python."
+msgstr "YOU CAN IMPLEMENT NEW @VALUE{GDBN} PARAMETERS USING PYTHON."
diff --git a/t/fmt/texinfoparser/tindex.pot b/t/fmt/texinfoparser/tindex.pot
new file mode 100644
index 00000000..6c02161c
--- /dev/null
+++ b/t/fmt/texinfoparser/tindex.pot
@@ -0,0 +1,47 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @cindex
+#: tindex.texi:3
+#, no-wrap
+msgid "parameters in python"
+msgstr ""
+
+#. type: line_arg 1 in @cindex
+#: tindex.texi:4
+#, no-wrap
+msgid "python parameters"
+msgstr ""
+
+#. type: line_arg 1 in @tindex
+#: tindex.texi:7
+#, no-wrap
+msgid "gdb.Parameter"
+msgstr ""
+
+#. type: line_arg 1 in @tindex
+#: tindex.texi:8
+#, no-wrap
+msgid "Parameter"
+msgstr ""
+
+#. type: paragraph
+#: tindex.texi:9
+#, no-wrap
+msgid "You can implement new @value{GDBN} parameters using Python."
+msgstr ""
diff --git a/t/fmt/texinfoparser/tindex.texi b/t/fmt/texinfoparser/tindex.texi
new file mode 100644
index 00000000..be47e18e
--- /dev/null
+++ b/t/fmt/texinfoparser/tindex.texi
@@ -0,0 +1,9 @@
+\input texinfo
+
+@cindex parameters in python
+@cindex python parameters
+@documentencoding UTF-8
+@documentlanguage en
+@tindex gdb.Parameter
+@tindex Parameter
+You can implement new @value{GDBN} parameters using Python.
diff --git a/t/fmt/texinfoparser/tindex.trans b/t/fmt/texinfoparser/tindex.trans
new file mode 100644
index 00000000..5900bfdd
--- /dev/null
+++ b/t/fmt/texinfoparser/tindex.trans
@@ -0,0 +1,9 @@
+\input texinfo
+
+@cindex PARAMETERS IN PYTHON
+@cindex PYTHON PARAMETERS
+@documentencoding UTF-8
+@documentlanguage en
+@tindex GDB.PARAMETER
+@tindex PARAMETER
+YOU CAN IMPLEMENT NEW @VALUE{GDBN} PARAMETERS USING PYTHON.
diff --git a/t/fmt/texinfoparser/tindex.trans.stderr b/t/fmt/texinfoparser/tindex.trans.stderr
new file mode 100644
index 00000000..81aa451d
--- /dev/null
+++ b/t/fmt/texinfoparser/tindex.trans.stderr
@@ -0,0 +1,5 @@
+po4a::texinfo: tindex.texi:3: warning: entry for index `cp' outside of any node
+po4a::texinfo: tindex.texi:4: warning: entry for index `cp' outside of any node
+po4a::texinfo: tindex.texi:7: warning: entry for index `tp' outside of any node
+po4a::texinfo: tindex.texi:8: warning: entry for index `tp' outside of any node
+po4a::texinfo: tindex.texi:9: warning: undefined flag: GDBN
diff --git a/t/fmt/texinfoparser/topinifnotdocbook.norm b/t/fmt/texinfoparser/topinifnotdocbook.norm
new file mode 100644
index 00000000..76fac4f9
--- /dev/null
+++ b/t/fmt/texinfoparser/topinifnotdocbook.norm
@@ -0,0 +1,28 @@
+\input texinfo.tex
+
+@shorttitlepage My title
+
+@copying
+Some license it is
+
+@end copying
+
+@contents
+
+@ifnotdocbook
+@node Top
+@top top node in ifnotdocbook
+
+@insertcopying
+@end ifnotdocbook
+
+@menu
+* chap:: First chapter description
+@end menu
+
+@node chap
+@chapter Chapter one
+
+This is a manual.
+
+@bye
diff --git a/t/fmt/texinfoparser/topinifnotdocbook.po b/t/fmt/texinfoparser/topinifnotdocbook.po
new file mode 100644
index 00000000..853a819b
--- /dev/null
+++ b/t/fmt/texinfoparser/topinifnotdocbook.po
@@ -0,0 +1,71 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @shorttitlepage
+#: topinifnotdocbook.texi:3
+#, no-wrap
+msgid "My title"
+msgstr "MY TITLE"
+
+#. type: paragraph
+#: topinifnotdocbook.texi:6
+#, no-wrap
+msgid "Some license it is"
+msgstr "SOME LICENSE IT IS"
+
+#. type: @ifnotdocbook
+#: topinifnotdocbook.texi:12
+#, no-wrap
+msgid ""
+"@ifnotdocbook\n"
+"@node Top\n"
+"@top top node in ifnotdocbook\n"
+"\n"
+"@insertcopying\n"
+"@end ifnotdocbook"
+msgstr ""
+"@IFNOTDOCBOOK\n"
+"@NODE TOP\n"
+"@TOP TOP NODE IN IFNOTDOCBOOK\n"
+"\n"
+"@INSERTCOPYING\n"
+"@END IFNOTDOCBOOK"
+
+#. type: menu_entry
+#: topinifnotdocbook.texi:20
+#, no-wrap
+msgid "* chap:: First chapter description"
+msgstr "* CHAP:: FIRST CHAPTER DESCRIPTION"
+
+#. type: line_arg 1 in @node
+#: topinifnotdocbook.texi:23
+#, no-wrap
+msgid "chap"
+msgstr "CHAP"
+
+#. type: line_arg 1 in @chapter
+#: topinifnotdocbook.texi:24
+#, no-wrap
+msgid "Chapter one"
+msgstr "CHAPTER ONE"
+
+#. type: paragraph
+#: topinifnotdocbook.texi:26
+#, no-wrap
+msgid "This is a manual."
+msgstr "THIS IS A MANUAL."
diff --git a/t/fmt/texinfoparser/topinifnotdocbook.pot b/t/fmt/texinfoparser/topinifnotdocbook.pot
new file mode 100644
index 00000000..6ad997b5
--- /dev/null
+++ b/t/fmt/texinfoparser/topinifnotdocbook.pot
@@ -0,0 +1,65 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @shorttitlepage
+#: topinifnotdocbook.texi:3
+#, no-wrap
+msgid "My title"
+msgstr ""
+
+#. type: paragraph
+#: topinifnotdocbook.texi:6
+#, no-wrap
+msgid "Some license it is"
+msgstr ""
+
+#. type: @ifnotdocbook
+#: topinifnotdocbook.texi:12
+#, no-wrap
+msgid ""
+"@ifnotdocbook\n"
+"@node Top\n"
+"@top top node in ifnotdocbook\n"
+"\n"
+"@insertcopying\n"
+"@end ifnotdocbook"
+msgstr ""
+
+#. type: menu_entry
+#: topinifnotdocbook.texi:20
+#, no-wrap
+msgid "* chap:: First chapter description"
+msgstr ""
+
+#. type: line_arg 1 in @node
+#: topinifnotdocbook.texi:23
+#, no-wrap
+msgid "chap"
+msgstr ""
+
+#. type: line_arg 1 in @chapter
+#: topinifnotdocbook.texi:24
+#, no-wrap
+msgid "Chapter one"
+msgstr ""
+
+#. type: paragraph
+#: topinifnotdocbook.texi:26
+#, no-wrap
+msgid "This is a manual."
+msgstr ""
diff --git a/t/fmt/texinfoparser/topinifnotdocbook.texi b/t/fmt/texinfoparser/topinifnotdocbook.texi
new file mode 100644
index 00000000..76fac4f9
--- /dev/null
+++ b/t/fmt/texinfoparser/topinifnotdocbook.texi
@@ -0,0 +1,28 @@
+\input texinfo.tex
+
+@shorttitlepage My title
+
+@copying
+Some license it is
+
+@end copying
+
+@contents
+
+@ifnotdocbook
+@node Top
+@top top node in ifnotdocbook
+
+@insertcopying
+@end ifnotdocbook
+
+@menu
+* chap:: First chapter description
+@end menu
+
+@node chap
+@chapter Chapter one
+
+This is a manual.
+
+@bye
diff --git a/t/fmt/texinfoparser/topinifnotdocbook.trans b/t/fmt/texinfoparser/topinifnotdocbook.trans
new file mode 100644
index 00000000..c864823f
--- /dev/null
+++ b/t/fmt/texinfoparser/topinifnotdocbook.trans
@@ -0,0 +1,28 @@
+\input texinfo.tex
+
+@shorttitlepage MY TITLE
+
+@copying
+SOME LICENSE IT IS
+
+@end copying
+
+@contents
+
+@IFNOTDOCBOOK
+@NODE TOP
+@TOP TOP NODE IN IFNOTDOCBOOK
+
+@INSERTCOPYING
+@END IFNOTDOCBOOK
+
+@menu
+* CHAP:: FIRST CHAPTER DESCRIPTION
+@end menu
+
+@node CHAP
+@chapter CHAPTER ONE
+
+THIS IS A MANUAL.
+
+@bye
diff --git a/t/fmt/texinfoparser/topinifnottex.norm b/t/fmt/texinfoparser/topinifnottex.norm
new file mode 100644
index 00000000..c34006c3
--- /dev/null
+++ b/t/fmt/texinfoparser/topinifnottex.norm
@@ -0,0 +1,28 @@
+\input texinfo.tex
+
+@shorttitlepage My title
+
+@copying
+Some license it is
+
+@end copying
+
+@contents
+
+@ifnottex
+@node Top
+@top Old-style top node in ifnottex
+
+@insertcopying
+@end ifnottex
+
+@menu
+* chap:: First chapter description
+@end menu
+
+@node chap
+@chapter Chapter one
+
+This is a manual.
+
+@bye
diff --git a/t/fmt/texinfoparser/topinifnottex.po b/t/fmt/texinfoparser/topinifnottex.po
new file mode 100644
index 00000000..cb766d31
--- /dev/null
+++ b/t/fmt/texinfoparser/topinifnottex.po
@@ -0,0 +1,65 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @shorttitlepage
+#: topinifnottex.texi:3
+#, no-wrap
+msgid "My title"
+msgstr "MY TITLE"
+
+#. type: paragraph
+#: topinifnottex.texi:6
+#, no-wrap
+msgid "Some license it is"
+msgstr "SOME LICENSE IT IS"
+
+#. type: line_arg 1 in @node
+#: topinifnottex.texi:13
+#, no-wrap
+msgid "Top"
+msgstr "TOP"
+
+#. type: line_arg 1 in @top
+#: topinifnottex.texi:14
+#, no-wrap
+msgid "Old-style top node in ifnottex"
+msgstr "OLD-STYLE TOP NODE IN IFNOTTEX"
+
+#. type: menu_entry
+#: topinifnottex.texi:20
+#, no-wrap
+msgid "* chap:: First chapter description"
+msgstr "* CHAP:: FIRST CHAPTER DESCRIPTION"
+
+#. type: line_arg 1 in @node
+#: topinifnottex.texi:23
+#, no-wrap
+msgid "chap"
+msgstr "CHAP"
+
+#. type: line_arg 1 in @chapter
+#: topinifnottex.texi:24
+#, no-wrap
+msgid "Chapter one"
+msgstr "CHAPTER ONE"
+
+#. type: paragraph
+#: topinifnottex.texi:26
+#, no-wrap
+msgid "This is a manual."
+msgstr "THIS IS A MANUAL."
diff --git a/t/fmt/texinfoparser/topinifnottex.pot b/t/fmt/texinfoparser/topinifnottex.pot
new file mode 100644
index 00000000..3602b87f
--- /dev/null
+++ b/t/fmt/texinfoparser/topinifnottex.pot
@@ -0,0 +1,65 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @shorttitlepage
+#: topinifnottex.texi:3
+#, no-wrap
+msgid "My title"
+msgstr ""
+
+#. type: paragraph
+#: topinifnottex.texi:6
+#, no-wrap
+msgid "Some license it is"
+msgstr ""
+
+#. type: line_arg 1 in @node
+#: topinifnottex.texi:13
+#, no-wrap
+msgid "Top"
+msgstr ""
+
+#. type: line_arg 1 in @top
+#: topinifnottex.texi:14
+#, no-wrap
+msgid "Old-style top node in ifnottex"
+msgstr ""
+
+#. type: menu_entry
+#: topinifnottex.texi:20
+#, no-wrap
+msgid "* chap:: First chapter description"
+msgstr ""
+
+#. type: line_arg 1 in @node
+#: topinifnottex.texi:23
+#, no-wrap
+msgid "chap"
+msgstr ""
+
+#. type: line_arg 1 in @chapter
+#: topinifnottex.texi:24
+#, no-wrap
+msgid "Chapter one"
+msgstr ""
+
+#. type: paragraph
+#: topinifnottex.texi:26
+#, no-wrap
+msgid "This is a manual."
+msgstr ""
diff --git a/t/fmt/texinfoparser/topinifnottex.texi b/t/fmt/texinfoparser/topinifnottex.texi
new file mode 100644
index 00000000..c34006c3
--- /dev/null
+++ b/t/fmt/texinfoparser/topinifnottex.texi
@@ -0,0 +1,28 @@
+\input texinfo.tex
+
+@shorttitlepage My title
+
+@copying
+Some license it is
+
+@end copying
+
+@contents
+
+@ifnottex
+@node Top
+@top Old-style top node in ifnottex
+
+@insertcopying
+@end ifnottex
+
+@menu
+* chap:: First chapter description
+@end menu
+
+@node chap
+@chapter Chapter one
+
+This is a manual.
+
+@bye
diff --git a/t/fmt/texinfoparser/topinifnottex.trans b/t/fmt/texinfoparser/topinifnottex.trans
new file mode 100644
index 00000000..bdcdd072
--- /dev/null
+++ b/t/fmt/texinfoparser/topinifnottex.trans
@@ -0,0 +1,28 @@
+\input texinfo.tex
+
+@shorttitlepage MY TITLE
+
+@copying
+SOME LICENSE IT IS
+
+@end copying
+
+@contents
+
+@ifnottex
+@node TOP
+@top OLD-STYLE TOP NODE IN IFNOTTEX
+
+@insertcopying
+@end ifnottex
+
+@menu
+* CHAP:: FIRST CHAPTER DESCRIPTION
+@end menu
+
+@node CHAP
+@chapter CHAPTER ONE
+
+THIS IS A MANUAL.
+
+@bye
diff --git a/t/fmt/texinfoparser/verbatimignore.norm b/t/fmt/texinfoparser/verbatimignore.norm
new file mode 100644
index 00000000..05a813fd
--- /dev/null
+++ b/t/fmt/texinfoparser/verbatimignore.norm
@@ -0,0 +1,15 @@
+@node Top
+@top test verbatim and ignore
+
+@ignore @comment C on ignore
+ignored
+
+@example
+
+@end ignore @comment C on end ignore
+
+@verbatim @comment C on verbatim
+verbatîům
+
+@end iftex
+@end verbatim @comment C on end verbatim
diff --git a/t/fmt/texinfoparser/verbatimignore.po b/t/fmt/texinfoparser/verbatimignore.po
new file mode 100644
index 00000000..bcd24521
--- /dev/null
+++ b/t/fmt/texinfoparser/verbatimignore.po
@@ -0,0 +1,63 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @node
+#: verbatimignore.texi:1
+#, no-wrap
+msgid "Top"
+msgstr "TOP"
+
+#. type: line_arg 1 in @top
+#: verbatimignore.texi:2
+#, no-wrap
+msgid "test verbatim and ignore"
+msgstr "TEST VERBATIM AND IGNORE"
+
+#. type: @ignore
+#: verbatimignore.texi:4
+#, no-wrap
+msgid ""
+"@ignore @comment C on ignore\n"
+"ignored\n"
+"\n"
+"@example\n"
+"\n"
+"@end ignore @comment C on end ignore"
+msgstr ""
+"@IGNORE @COMMENT C ON IGNORE\n"
+"IGNORED\n"
+"\n"
+"@EXAMPLE\n"
+"\n"
+"@END IGNORE @COMMENT C ON END IGNORE"
+
+#. type: @verbatim
+#: verbatimignore.texi:11
+#, no-wrap
+msgid ""
+"@verbatim @comment C on verbatim\n"
+"verbatîům\n"
+"\n"
+"@end iftex\n"
+"@end verbatim @comment C on end verbatim"
+msgstr ""
+"@VERBATIM @COMMENT C ON VERBATIM\n"
+"VERBATÎŮM\n"
+"\n"
+"@END IFTEX\n"
+"@END VERBATIM @COMMENT C ON END VERBATIM"
diff --git a/t/fmt/texinfoparser/verbatimignore.pot b/t/fmt/texinfoparser/verbatimignore.pot
new file mode 100644
index 00000000..72d60cbb
--- /dev/null
+++ b/t/fmt/texinfoparser/verbatimignore.pot
@@ -0,0 +1,52 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2025-09-08 09:15+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: line_arg 1 in @node
+#: verbatimignore.texi:1
+#, no-wrap
+msgid "Top"
+msgstr ""
+
+#. type: line_arg 1 in @top
+#: verbatimignore.texi:2
+#, no-wrap
+msgid "test verbatim and ignore"
+msgstr ""
+
+#. type: @ignore
+#: verbatimignore.texi:4
+#, no-wrap
+msgid ""
+"@ignore @comment C on ignore\n"
+"ignored\n"
+"\n"
+"@example\n"
+"\n"
+"@end ignore @comment C on end ignore"
+msgstr ""
+
+#. type: @verbatim
+#: verbatimignore.texi:11
+#, no-wrap
+msgid ""
+"@verbatim @comment C on verbatim\n"
+"verbatîům\n"
+"\n"
+"@end iftex\n"
+"@end verbatim @comment C on end verbatim"
+msgstr ""
diff --git a/t/fmt/texinfoparser/verbatimignore.texi b/t/fmt/texinfoparser/verbatimignore.texi
new file mode 100644
index 00000000..05a813fd
--- /dev/null
+++ b/t/fmt/texinfoparser/verbatimignore.texi
@@ -0,0 +1,15 @@
+@node Top
+@top test verbatim and ignore
+
+@ignore @comment C on ignore
+ignored
+
+@example
+
+@end ignore @comment C on end ignore
+
+@verbatim @comment C on verbatim
+verbatîům
+
+@end iftex
+@end verbatim @comment C on end verbatim
diff --git a/t/fmt/texinfoparser/verbatimignore.trans b/t/fmt/texinfoparser/verbatimignore.trans
new file mode 100644
index 00000000..22cbc24b
--- /dev/null
+++ b/t/fmt/texinfoparser/verbatimignore.trans
@@ -0,0 +1,15 @@
+@node TOP
+@top TEST VERBATIM AND IGNORE
+
+@IGNORE @COMMENT C ON IGNORE
+IGNORED
+
+@EXAMPLE
+
+@END IGNORE @COMMENT C ON END IGNORE
+
+@VERBATIM @COMMENT C ON VERBATIM
+VERBATÎŮM
+
+@END IFTEX
+@END VERBATIM @COMMENT C ON END VERBATIM
