Multi language browse using display sentence.

Hi, there.
I would like to know whether is posible to have multi language using the following code:
I want to avoid input using map sentence.

re-prs. Read personal-file with personal-id
callnat ‘display&’ using personal-file-paramenters
‘display1’ subprogram -> display ‘identification’ personal-id ‘name’ name ‘salary’ salary
‘display4’ subprogram -> display ‘identificacion’ personal-id ‘nombre’ name ‘salario’ salary
end-read
end
Is it possible ?
Any other flexible idea ?

You may want to use WRITE TITLE to display different headers based on *LANGUAGE

Thank you Wolfgang.
Is it posible to use write T* in order to sum(salary) ?

The DISPLAY statement is one of Natural’s best features: all that effortless columnar report formatting. But to do that formatting, Natural needs to know the header content at compile time, and you need dynamic headers to allow for multiple languages.

The problem with your solution is the maintenance of multiple modules, each of which is identical except for the DISPLAY’s header. The typical solution is to create a single reporting program with multiple maps for the output - one map per language. But this would not allow the use of built-in functions, such as SUM.

Here is an alternative. Use DISPLAY, but override the header with WRITE TITLE or AT TOP OF PAGE. The problem with this solution is the time it takes to create and adjust the custom header.

Good luck.

DEFINE DATA LOCAL
1 EMP    VIEW EMPLOYEES
  2 PERSONNEL-ID
  2 NAME
  2 SALARY (1)
1 #EGFS (4)                                       /* headers
  2 #ID (A15)      INIT <'Identification'
                        ,'Identifizierung'
                        ,'Identification'
                        ,'Identificación'
                        >
  2 #NAME (A6)     INIT <'Name'
                        ,'Name'
                        ,'Prénom'
                        ,'Nombre'
                        >
  2 #SALARY (A7)   INIT <'Salary'
                        ,'Gehalt'
                        ,'Salaire'
                        ,'Salario'
                        >
1 #L (I4)          INIT <*LANGUAGE>
1 #PROGRAM (A8)    INIT <*PROGRAM>
END-DEFINE
ASSIGN *LANGUAGE =  4    /* testing
ASSIGN #L = *LANGUAGE    /* testing
LIMIT 5
READ EMP BY PERSONNEL-ID
  DISPLAY NOHDR (SF=2)
           EMP.PERSONNEL-ID (AL=15)
           EMP.NAME
           EMP.SALARY (1)
  AT BREAK OF EMP.PERSONNEL-ID
    WRITE T*EMP.SALARY SUM (EMP.SALARY (1))
  END-BREAK
END-READ
*
WRITE TITLE LEFT
          #PROGRAM
      10T 'Javier"s Multi-Lang Headers'
   // 10T 'Language Code:' #L (AD=L SG=F)
   //     #ID (#L)
      18T #NAME (#L)
      40T #SALARY (#L)
    /     '-' (15)
      18T '-' (20)
      40T '-' (10)
    /
END
JAVIER   JAVIER's Multi-Lang Headers
 
         LANGUAGE CODE: 4
 
IDENTIFICACIÓN   NOMBRE                SALARIO
---------------  --------------------  ----------
 
11100102         SCHINDLER                  24615
                                            24615
11100105         SCHIRM                     34871
                                            34871
11100106         SCHMITT                    26153
                                            26153
11100107         SCHMIDT                    18461
                                            18461
11100108         SCHNEIDER                  22564
                                            22564
1 Like

Ralph, it is a good alternative.
Thank you for your help.

As Ralph said, DISPLAY is a very powerful statement. Among other things, it permits multi line headers.

For example:

DISPLAY ‘SALARIO/SALARY’ SALARY

If you are only working with two languages, this might be a viable, and simple solution for what you described.

If you are working with more languages, the problem can become quite messy. How likely is it that a page of output will have just one or two languages?

I presume (perhaps incorrectly) that the real determinant for headers is the “user” who will be reading the report. If so, you might require something (a variable, a user-id for the individual running the program (if online rather than batch)) to generate different headers.

So, two questions.

  1. How many languages are involved
  2. Is it the language of a record, or the language of the user that is most important.

With regard to your question regarding T* (a wonderful feature that is not used nearly as often as it should be), the answer is yes. That is, regardless of the length of headers, and how many lines of headers you have, you can always T* to the variable being displayed. Natural will always tab to the proper place based on the starting point of the column for a variable.

1 Like

Thank you Steve.

Yes it is, Display Command is very useful, flexible and easy to maintain including write t* command.

  1. There are 4 languages online involved -> maximum
  2. It is the language of the user.

Given the possibility of four user languages, I would use the AT TOP OF PAGE clause. Something like:
AT TOP OF PAGE
DECIDE ON VALUE OF #USER
VALUE 1
WRITE header for 1st language
VALUE 2
WRITE header for second language
etc.

The important thing, of course, is to be able to identify the language the user requires. That is, obtain appropriate values for #USER (1 through 4). This could be done via an INPUT statement, or something like *USER, or a logon id.

As a follow up to what I posted;

AT TOP OF PAGE would be best if the same user might request several different languages for a given report, or just different languages for different reports.

If the user always wants the same language throughout their “session”, I would test #USER at the beginning of the program, then move one of four languages to a single variable. Then I would use a single WRITE TITLE #HEADERS for every page.

Steve, thank you very much for your posts.
Now, I would like to find any browse natural program to compare.
Is there any base program to download ?
Do you recommend any website link ?

Javier,
What do you mean by a “browse Natural program”?
There are many ways to access Adabas files; e.g. READ PHYSICAL, READ LOGICAL, READ BY ISN, FIND.
Which one were you going to give to an end-user?
Did you intend to retrieve records that satisfied one criteria? Or, ranges of values?

I mean a program to browse/scroll PF7/PF8 using Read Logical.
There are many ways to do it and i thought about an example program to do that in this forum.

Javier;

Could you outline what you want the browser to do? For example, what you posted (PF7 and PF8 functionality), plus the ability to skip forward/backward to a given value plus the next n records.

If you would post your example program mentioned in your last post, we would be able to suggest alternatives.

Here you have it.
It is a program ready to be called via stack or to call others via stack too.

0010 DEFINE DATA
0020 LOCAL
0030 1 EMPLOYEES-VIEW VIEW OF EMPLOYEES
0040 2 PERSONNEL-ID (A8)
0050 2 FIRST-NAME (A20)
0060 2 NAME (A20)
0070 2 SEX (A1)
0080 2 BIRTH (D)
0090 2 CITY (A20)
0100 2 COUNTRY (A3)
0110 2 JOB-TITLE (A25)
0120 1 EOF (L)
0130 1 X (P3)
0140 1 S (P3)
0150 1 #PROGRAM (A8) INIT <PROGRAM>
0160 1 INPUT-DATA
0170 2 #PAGE-NUMBER(P3)
0180 2 #PERSONNEL-ID (A8)
0190 2 #STACK (L)
0200 END-DEFINE
0210 *
0220 SET KEY ALL
0230 SET KEY PF7 NAMED ‘-’ PF8 NAMED ‘+’
0240 SET KEY PF3 NAMED ‘End’
0250 IF DATA > 0
0260 INPUT (AD=M’_’) INPUT-DATA
0270 END-IF
0280 READ EMPLOYEES-VIEW
0290 WITH PERSONNEL-ID = #PERSONNEL-ID THRU ‘11200308’ /
H’FF’ /
‘11100330’
0300 DISPLAY LINE-COUNT COUNTER PERSONNEL-ID JOB-TITLE FIRST-NAME SEX
0310 AT END OF DATA
0320 MOVE TRUE TO EOF
0330 WRITE NOTITLE ’
end of data **’
0340 END-ENDDATA
0350 END-READ
0360 AT TOP OF PAGE
0370 IF #STACK
0380 RESET #STACK
0390 ELSE
0400 ADD 1 TO #PAGE-NUMBER
0410 END-IF
0420 MOVE PERSONNEL-ID TO #PERSONNEL-ID
0430 WRITE NOTITLE ‘page’ #PAGE-NUMBER ‘id’ #PERSONNEL-ID ‘date’ *DATX ‘=’ *DATA
0440 END-TOPPAGE
0450 AT END OF PAGE
0460 REPEAT UNTIL *LINE-COUNT = PAGESIZE
0470 SKIP 1
0480 END-REPEAT
0490 INPUT (AD=M’’) *COM (AD=M’’ AL=60)
0500 DECIDE ON FIRST VALUE PF-KEY
0510 VALUE ‘PF8’,‘ENTR’
0520 IF EOF
0530 REINPUT ’
end of data ’ ALARM
0540 END-IF
0550 STACK TOP DATA #PAGE-NUMBER #PERSONNEL-ID ‘X’
0560 STACK TOP COMMAND PROGRAM
0570 VALUE ‘PF7’
0580 IF #PAGE-NUMBER = 1
0590 REINPUT ’
start of data ’ ALARM
0600 END-IF
0610 STOP
0620 VALUE ‘PF3’
0630 IF #PAGE-NUMBER > 1
0640 COMPUTE S = #PAGE-NUMBER - 1
0650 FOR X = 1 TO S /
Delete PF7 Stacks
0660 SET CONTROL ‘.P’ /
delete stack program
0670 SET CONTROL ‘.P’ /
delete stack data
0680 END-FOR
0690 END-IF
0700 STOP
0710 NONE VALUE
0720 REINPUT (CD=RE) ‘ERROR: invalid PF-key’ ALARM
0730 END-DECIDE
0740 END-ENDPAGE
0750 *
0760 *
0770 *
0780 END

I wouldn’t have expected anyone these days to try to write a browse program from scratch. Natural shops are mature, all having many production examples of such a program, whether created in-house or generated by Natural Construct.

That being said, it looks like you had fun getting this to work. Too bad that its design flaws would keep it from going to production. It might be OK for the odd ad hoc, though.

STACK TOP COMMAND *PROGRAM

I see this as the biggest problem. Re-establishing the module’s addressability every time ENTER or a PF key is pressed is way too much overhead.

AT END OF PAGE
...
INPUT (AD=M'_') *COM 

You are giving the user control within an Adabas access loop (READ), breaking a cardinal rule of Natural programming.

AT END OF DATA
MOVE TRUE TO EOF

If the user requests a starting point beyond the end of the file, the program stops with no error message.

The basic structure should be

REPEAT
    INPUT        /* to accept criteria or display output array
    DECIDE     /* test PF keys
        ...
    END-DECIDE
    READ file
        load array
    END-READ
END-REPAT

I agree with Ralph’s last post, except for one point. Depending on what system and version number you are running, you might want to take a look at READ … WITH REPOSITION in the documentation for your system to see if it is there.

The following code is from the latest mainframe documentation:

DEFINE DATA LOCAL
1 MYVIEW VIEW OF …
2 NAME
1 #STARTVAL (A20) INIT <‘A’>
1 #ATTR ©
END-DEFINE

SET KEY PF3

READ MYVIEW WITH REPOSITION BY NAME = #STARTVAL
INPUT (IP=OFF AD=O) ‘NAME:’ NAME /
‘Enter new start value for repositioning:’ #STARTVAL (AD=MT CV=#ATTR) /
‘Press PF3 to stop’
IF *PF-KEY = ‘PF3’
THEN STOP
END-IF
IF #ATTR MODIFIED
THEN ESCAPE TOP REPOSITION
END-IF
END-READ

There are a few modifications I would make to this code.

If you need to see a few data fields of each record you might want to work with say ten records per screen. You could accomplish this by setting page size accordingly.

I would then put the INPUT statement through the second IF inside of an AT END OF PAGE clause. Then I would do an INPUT NO ERASE not a simple INPUT, positioned below the ten records.

From here you are limited only by your imagination your knowledge of Natural, and what you might want to do with “selected” records. In the INPUT NO ERASE statement you could have a place for a number to be entered corresponding to numbering the screen records 1 to 10. The within the READ loop you could do a GET ISN for the record selected, assuming you DISPLAYed the ISNs.

Add some color (CD= ) and perhaps some reverse video, and you will have a program that people will not believe is written in Natural.