GEP 18: 1. Source templates as new plugin type

2. EE templates in their own plugin, loading from csv in data


svn: r22611
This commit is contained in:
Benny Malengier 2013-06-25 22:26:56 +00:00
parent 5b6da40866
commit 0a2580e9c5
13 changed files with 1234 additions and 8694 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
#
# 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
This module parses the evidence csv file and generates the code we need in
Gramps to use the evidence style.
"""
#-------------------------------------------------------------------------
#
# Standard Python modules
#
#-------------------------------------------------------------------------
import csv
#-------------------------------------------------------------------------
#
# Code
#
#-------------------------------------------------------------------------
csvfilename = "evidence_style.csv"
NRCOL = 0
CATCOL = 1
CATTYPECOL = 2
TYPECOL = 3
DESCRCOL= 4
CITETYPECOL = 5
IDENTCOL = 6
LDELCOL = 7 # left delimiter
FIELDCOL = 8
LABELCOL = 9
RDELCOL = 10 # right delimiter
GEDCOMCOL = 11
SHORTERCOL = 12
STYLECOL = 13
PRIVACYCOL = 14
OPTCOL = 15
HINTCOL = 16
TOOLTIPCOL = 17
first = True
trans = {}
with open(csvfilename, 'rb') as csvfile:
reader = csv.reader(csvfile, delimiter=';')
for row in reader:
if first:
first=False
continue
elif row[CATCOL]:
cat = row[CATCOL].strip()
cattype = row[CATTYPECOL].strip()
types = row[TYPECOL].strip()
descr = row[DESCRCOL].strip()
for val in [cat, cattype, types, descr]:
if val and val not in trans:
trans[val] = '_("' + val + '")'
val = row[HINTCOL]
if val and val not in trans:
trans[val] = '_("' + val + '")'
val = row[TOOLTIPCOL]
if val and val not in trans:
trans[val] = '_("' + val + '")'
#now generate the python code we need in source attr types
code = "#following translations are generated with extract_trans_csv.py\n"
code += "if False:\n"
code += " #these translations will only occur when needed first time!\n"
allkeys = sorted(trans.keys())
for field in allkeys:
code += " " + trans[field] + '\n'
with open('csv_trans.py', 'wb') as srcattrfile:
srcattrfile.write(code)

View File

@ -23,6 +23,10 @@
"""
SrcAttributeBase class for GRAMPS.
"""
from __future__ import print_function
from ..const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#-------------------------------------------------------------------------
#
@ -61,26 +65,23 @@ class SrcAttributeBase(AttributeRootBase):
for attr in self.attribute_list:
if int(attr.get_type()) == SrcAttributeType.SRCTEMPLATE:
val = attr.get_value()
try:
templ = SrcTemplate.K2I_SRCTEMPLATEMAP[val]
except KeyError:
if SrcTemplate.template_defined(val):
templ = val
else:
# a template not in the predefined list. convert to unknown
print ('SrcAttributeBase: Keyerror "', val,
'"for now UNKNOWN taken, later custom templates?')
print ('Unknown Template: Keyerror "', val,
'"for now UNKNOWN taken.\nDownload required template style!')
break
try:
retval = (templ, SrcTemplate.I2S_SRCTEMPLATEMAP[templ],
SrcTemplate.I2K_SRCTEMPLATEMAP[templ])
retval = (templ, SrcTemplate.template_description(templ))
except KeyError:
#templ is not present, return the default GEDCOM value as actual
#template
templ = SrcTemplate.UNKNOWN
retval = (templ,
SrcTemplate.I2S_SRCTEMPLATEMAP[SrcTemplate.UNKNOWN],
SrcTemplate.I2K_SRCTEMPLATEMAP[SrcTemplate.UNKNOWN])
retval = (templ, _('Unknown'))
return retval
def set_source_template(self, tempindex, tempcustom_str):
def set_source_template(self, template):
"""
Set the source template of the source/citation
This is the value of the first source template in the attribute list
@ -101,11 +102,8 @@ class SrcAttributeBase(AttributeRootBase):
#we create a new attribute and add it
attrtemp = SrcAttribute()
self.add_attribute(attrtemp)
if tempindex == SrcTemplate.UNKNOWN or \
(tempindex == SrcTemplate.CUSTOM and tempcustom_str.strip() == ''):
if template == SrcTemplate.UNKNOWN:
self.remove_attribute(attrtemp)
elif not (tempindex == SrcTemplate.CUSTOM):
attrtemp.set_value(SrcTemplate.I2K_SRCTEMPLATEMAP[tempindex])
else:
#custom key, store string as is
attrtemp.set_value(tempindex)
attrtemp.set_value(template)

View File

@ -117,9 +117,9 @@ class SrcAttributeType(GrampsType):
(EVEN_ROLE , _("Role in Event Cited from"), "Role in Event Cited from"), # GEDCOM ROLE_IN_EVENT
(GEN_BY , _("Generated by"), "Generated by"), # Generated sources on import
(REPOSITORY, _("Repository"), "Repository"),
(REPOSITORY_ADDRESS, _("Repository Address"), "Repository Address"),
(REPOSITORY_ADDRESS, _("Repository address"), "Repository address"),
(REPOSITORY_SHORT_VERSION, _("Repository (Short)"), "Repository (Short)"),
(REPOSITORY_CALL_NUMBER, _("Repository Call Number"), "Repository Call Number"),
(REPOSITORY_CALL_NUMBER, _("Repository call number"), "Repository call number"),
(DATE, _("Date"), "Date"),
# possible fields for evidence styles need to be added next
]

File diff suppressed because it is too large Load Diff

View File

@ -386,6 +386,16 @@ class BasePluginManager(object):
"""
return self.__pgr.sidebar_plugins()
def get_reg_srctemplates(self):
""" Return list of registered sidebars. Only non-hidden templates
are returned, as srctemplate plugins can redifine templates of other
plugins. By setting hidden, user can select style he wants
"""
#sr
hidden_plugins = set(config.get('plugin.hiddenplugins'))
return [plg for plg in self.__pgr.srctemplate_plugins()
if plg.id not in hidden_plugins]
def get_external_opt_dict(self):
""" Return the dictionary of external options. """
return self.__external_opt_dict

View File

@ -74,8 +74,9 @@ VIEW = 8
RELCALC = 9
GRAMPLET = 10
SIDEBAR = 11
SRCTEMPLATE = 12
PTYPE = [REPORT , QUICKREPORT, TOOL, IMPORT, EXPORT, DOCGEN, GENERAL,
MAPSERVICE, VIEW, RELCALC, GRAMPLET, SIDEBAR]
MAPSERVICE, VIEW, RELCALC, GRAMPLET, SIDEBAR, SRCTEMPLATE]
PTYPE_STR = {
REPORT: _('Report') ,
QUICKREPORT: _('Quickreport'),
@ -89,6 +90,7 @@ PTYPE_STR = {
RELCALC: _('Relationships'),
GRAMPLET: _('Gramplet'),
SIDEBAR: _('Sidebar'),
SRCTEMPLATE: _('Source Templates'),
}
#possible report categories
@ -990,6 +992,7 @@ def make_environment(**kwargs):
'RELCALC': RELCALC,
'GRAMPLET': GRAMPLET,
'SIDEBAR': SIDEBAR,
'SRCTEMPLATE': SRCTEMPLATE,
'CATEGORY_TEXT': CATEGORY_TEXT,
'CATEGORY_DRAW': CATEGORY_DRAW,
'CATEGORY_CODE': CATEGORY_CODE,
@ -1262,6 +1265,11 @@ class PluginRegister(object):
"""
return self.type_plugins(SIDEBAR)
def srctemplate_plugins(self):
"""Return a list of PluginData that are of type SRCTEMPLATE
"""
return self.type_plugins(SRCTEMPLATE)
def filter_load_on_reg(self):
"""Return a list of PluginData that have load_on_reg == True
"""

View File

@ -123,7 +123,7 @@ class SrcTemplateTab(GrampsTab):
:param scrolled: GtkScrolledWindow to which to add treeview with templates
"""
templ = self.src.get_source_template()
self.temp_tv = SrcTemplateTreeView(templ[2],
self.temp_tv = SrcTemplateTreeView(templ[0],
sel_callback=self.on_template_selected)
scrolled.add(self.temp_tv)
@ -155,15 +155,15 @@ class SrcTemplateTab(GrampsTab):
# which will update the title in the source object
self.callback_src_changed()
def on_template_selected(self, index, key):
def on_template_selected(self, key):
"""
Selected template changed, we save this and update interface
"""
self.src.set_source_template(index, key)
self.src.set_source_template(key)
self.callback_src_changed(templatechanged=True)
#a predefined template,
self.tmplfields.reset_template_fields(index)
self.tmplfields.reset_template_fields(key)
#-------------------------------------------------------------------------
#
@ -197,15 +197,15 @@ class TemplateFields(object):
self.btns = []
self.monentry = []
def reset_template_fields(self, index):
def reset_template_fields(self, key):
"""
Method that constructs the actual fields where user can enter data.
Template must be the index of the template.
"""
#obtain the template of the index
if index in SrcTemplate.EVIDENCETEMPLATES:
#obtain the template of the key
if SrcTemplate.template_defined(key):
#a predefined template,
template = SrcTemplate.EVIDENCETEMPLATES[index]
template = SrcTemplate.get_template(key)
else:
return
@ -467,45 +467,3 @@ class TemplateFields(object):
foundattr.set_type(srcattrtype)
foundattr.set_value(value)
obj.add_attribute(foundattr)
## def setup_autocomp_combobox(self):
## """
## Experimental code to set up a combobox with all templates.
## This is too slow, we use treeview in second attempt
## """
## self.srctempcmb = Gtk.ComboBox(has_entry=True)
## ignore_values = []
## custom_values = []
## srcattr = SrcAttributeType()
## default = srcattr.get_templatevalue_default()
## maptempval = srcattr.get_templatevalue_map().copy()
## if ignore_values :
## for key in list(maptempval.keys()):
## if key in ignore_values and key not in (None, default):
## del map[key]
##
## self.sel = StandardCustomSelector(
## maptempval,
## self.srctempcmb,
## srcattr.get_custom(),
## default,
## additional=custom_values)
##
## templ = self.src.get_source_template()
## self.sel.set_values((templ[0], templ[1]))
## self.srctempcmb.set_sensitive(not self.readonly)
## self.srctempcmb.connect('changed', self.on_change_template)
## srctemphbox.pack_start(self.srctempcmb, False, True, 0)
##
## return topvbox
## def fix_value(self, value):
## if value[0] == SrcAttributeType.CUSTOM:
## return value
## else:
## return (value[0], '')
##
## def on_change_template(self, obj):
## #value = self.fix_value(self.srctempcmb.get_values())
## value = self.sel.get_values()
## self.src.set_source_template(value[0], value[1])

View File

@ -317,4 +317,10 @@ class GuiPluginManager(Callback):
def get_reg_general(self, category=None):
return [plg for plg in self.basemgr.get_reg_general(category)
if plg.id not in self.__hidden_plugins]
def get_reg_srctemplates(self):
"""
Obtain registered SrcTemplates
Srctemplates are already filtered on hidden in the base manager
"""
return self.basemgr.get_reg_srctemplates()

View File

@ -78,19 +78,14 @@ class SrcTemplateTreeView(Gtk.TreeView):
"""
Obtains all templates and stores them in a TreeStore
"""
srctemp = SrcTemplate()
self.I2Str = srctemp.I2S_SRCTEMPLATEMAP
self.I2Key = srctemp.I2K_SRCTEMPLATEMAP
self.Str2I = srctemp.S2I_SRCTEMPLATEMAP
self.Key2I = srctemp.K2I_SRCTEMPLATEMAP
self.Key2Path = {}
# store (index, key, src_type)
self.model = Gtk.TreeStore(int, str, str)
alltexts = sorted(self.Str2I.keys())
# store (key, src_type)
self.model = Gtk.TreeStore(str, str)
alltexts = sorted((SrcTemplate.template_description(x), x) for x in SrcTemplate.all_templates())
parentiter = None
parentiterlev1 = None
prevstrval = ['', '']
for alltext in alltexts:
for alltext, key in alltexts:
vals = alltext.split('-')
if len(vals) > 3:
vals = [vals[0], vals[1], ' - '.join(vals[2:])]
@ -105,8 +100,7 @@ class SrcTemplateTreeView(Gtk.TreeView):
if len(vals) < 3 :
truevals[:len(vals)] = vals[:]
vals = truevals
index = self.Str2I[alltext]
row = [index, self.I2Key[index], lastval]
row = [key, lastval]
iter = None
if prevstrval[0] == vals[0] and prevstrval[1] == vals[1]:
#same parentiter
@ -115,33 +109,33 @@ class SrcTemplateTreeView(Gtk.TreeView):
#up one parentiter, make new sublevel2 if needed
parentiter = parentiterlev1
if vals[2]:
parentiter = self.model.append(parentiter, [-10, '', vals[1]])
parentiter = self.model.append(parentiter, ['', vals[1]])
iter = self.model.append(parentiter, row)
else:
#new value
parentiterlev1 = None
if vals[2] and vals[1]:
#new sublevel1 and 2 needed
parentiterlev1 = self.model.append(None, [-10, '', vals[0]])
parentiterlev1 = self.model.append(None, ['', vals[0]])
#make sublevel2
parentiter= self.model.append(parentiterlev1, [-10, '', vals[1]])
parentiter= self.model.append(parentiterlev1, ['', vals[1]])
iter = self.model.append(parentiter, row)
elif vals[1]:
#only new sublevel1 needed
parentiterlev1 = self.model.append(None, [-10, '', vals[0]])
parentiterlev1 = self.model.append(None, ['', vals[0]])
parentiter = parentiterlev1
iter = self.model.append(parentiter, row)
else:
#only a top level
iter = self.model.append(None, row)
#store key to path
self.Key2Path[row[1]] = self.model.get_path(iter)
self.Key2Path[row[0]] = self.model.get_path(iter)
prevstrval = [vals[0], vals[1]]
def make_columns(self):
#make the column in the treeview
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn(_("Template"), renderer, text=2)
column = Gtk.TreeViewColumn(_("Template"), renderer, text=1)
self.append_column(column)
#no headers needed:
self.set_headers_visible (False)
@ -151,7 +145,6 @@ class SrcTemplateTreeView(Gtk.TreeView):
highlight key in the view
"""
#we determine the path of key
path = self.Key2Path[key]
iter_ = self.model.get_iter(path)
if iter_:
@ -169,7 +162,7 @@ class SrcTemplateTreeView(Gtk.TreeView):
self.selection.unselect_all()
self.selection.select_path(path)
self.scroll_to_cell(path, None, 1, 0.5, 0)
self.sel_callback(self.Key2I[key], key)
self.sel_callback(key)
def get_selected(self):
"""
@ -177,7 +170,7 @@ class SrcTemplateTreeView(Gtk.TreeView):
"""
(model, node) = self.selection.get_selected()
if node:
return (model.get_value(node, 0), model.get_value(node,1), node)
return (model.get_value(node, 0), node)
return None
def _on_button_release(self, obj, event):
@ -186,8 +179,8 @@ class SrcTemplateTreeView(Gtk.TreeView):
"""
if event.type == Gdk.EventType.BUTTON_RELEASE and event.button == 1:
ref = self.get_selected()
if ref and ref[0] != -10:
self.sel_callback(ref[0], ref[1])
if ref and ref[0] != '':
self.sel_callback(ref[0])
return False
def _on_key_press_event(self, widget, event):
@ -195,10 +188,10 @@ class SrcTemplateTreeView(Gtk.TreeView):
if event.keyval in (Gdk.KEY_Return, Gdk.KEY_KP_Enter):
ref = self.get_selected()
if ref:
if ref[0] != -10:
self.sel_callback(ref[0], ref[1])
if ref[0] != '':
self.sel_callback(ref[0])
else:
path = self.model.get_path(ref[2])
path = self.model.get_path(ref[0])
if self.row_expanded(path):
self.collapse_row(path)
else:

View File

View File

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
#
# 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Registering srctemplates for GRAMPS.
"""
#
# SrcTemplates distributed with Gramps
#
# EE
plg = newplugin()
plg.id = 'evidence explained styles'
plg.name = _("Evidence Explained Source Templates")
plg.description = _("Defines source templates corresponding with those from the"
" book Evidence Explained.")
plg.version = '1.0'
plg.gramps_target_version = '4.1'
plg.status = STABLE
plg.fname = 'evidenceexplained.py'
plg.ptype = SRCTEMPLATE

View File

@ -0,0 +1,262 @@
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
#
# 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Registering srctemplates for GRAMPS.
"""
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
import os
from functools import partial
from gramps.gen.const import DATA_DIR
#
# SrcTemplates distributed with Gramps
#
# Add EE styles to the src templates defined
#the csv file with the template definitions
path_csv = partial(os.path.join, DATA_DIR, "evidencestyle")
csvfile = path_csv('evidence_style.csv')
#name of this style
style = 'EE'
#strings to translate
#following translations are generated with extract_trans_csv.py
if False:
#these translations will only occur when needed first time!
_("1790-1840")
_("1850-1860: slaves")
_("1850-1870")
_("1880-1930")
_("Abstracts")
_("Administrative material")
_("Appeals court record books")
_("Application file")
_("Archival preservation copy")
_("Archived Material")
_("Archived in-house")
_("Archived off-site")
_("Archives & Artifacts")
_("Artifact")
_("Audio book")
_("Audio recordings")
_("Basic Format")
_("Blogs")
_("Book")
_("Book:")
_("Bound volume")
_("Broadcasts & Web Miscellanea")
_("Business & institutional Records")
_("CD-ROM publication")
_("CD/DVD")
_("CD/DVD book (text)")
_("CD/DVD publication")
_("Case Reporters")
_("Case files")
_("Cemetery Office Records")
_("Cemetery Records")
_("Cemetery abstracts")
_("Census Records")
_("Church Books")
_("Church Records")
_("Church record book, recopied")
_("Church-issued certificate")
_("Church-records database")
_("Citing volume from title page")
_("Codes & statutes, online")
_("Collection, emphasis on")
_("Congressional Records")
_("Corporate Records")
_("Database")
_("Database online")
_("Databases")
_("Derivatives")
_("Descriptive pamphlet, online")
_("Diary or journal, etc.")
_("Digital Archives")
_("Digital Images")
_("Digitized online")
_("Discussion forums & lists")
_("Document (loose record)")
_("Document, emphasis on")
_("Electronic Publications")
_("Extract supplied by staff")
_("FHL-GSU film")
_("FHL-GSU preservation")
_("FHL-GSU preservation copy")
_("FHL-GSU preservation film")
_("Family Bible Records")
_("Family Chart or Group Sheet")
_("File items")
_("Files moved to state archives")
_("France")
_("Genetic testing")
_("Grave markers")
_("Historic letter")
_("Historical research: corporate")
_("Historical research: online")
_("Image Copies")
_("Images online")
_("In-house film")
_("Interview tape & transcript")
_("Journal articles")
_("LDS records at FHL")
_("Land warrants: loose")
_("Land-grant register")
_("Leaflet")
_("Legal Reference Works")
_("Legal document, unrecorded")
_("Legislative petitions & files")
_("Library of Congress")
_("Lineage-society Records")
_("Local")
_("Local & State Records: Courts & Governance")
_("Local & State Records: Licenses, Registrations, Rolls & Vital Records")
_("Local & State Records: Property & Probates")
_("Local Records")
_("Local copy")
_("Magazine articles")
_("Manuscript Records")
_("Manuscripts")
_("Map")
_("Maps")
_("Markers & Memorials (Originals)")
_("Memorial plaques")
_("Microfilm")
_("Microfilm (U.S.)")
_("Microfilm publication")
_("Miscellaneous file")
_("NARA Style citation")
_("NARA film")
_("Named volume")
_("National Archives")
_("National Archives (Australia)")
_("National Archives (Canada)")
_("National Archives (U.K.)")
_("National Archives (U.S.)")
_("National Archives (U.S.) guides")
_("National Archives copy")
_("National Archives microfilm")
_("National Archives-Regional")
_("National Government Records")
_("Native-American tribal census")
_("Newsletter articles")
_("Newspaper articles")
_("Nonpopulation schedules")
_("Numbered volume")
_("Office records")
_("Online")
_("Online archives")
_("Online archives of print journals")
_("Online commercial site")
_("Online database")
_("Online image")
_("Online images")
_("Online journals")
_("Online publication")
_("Online reprints, random items")
_("Online:")
_("Organizational Records")
_("Original Materials (U.S.)")
_("Original Records")
_("Original manuscripts (U.S.)")
_("Patent & Trademark Office (U.S.)")
_("Periodicals")
_("Personal Bible")
_("Personal correspondence")
_("Personal e-mail")
_("Photographs")
_("Podcasts")
_("Population schedules")
_("Portrait")
_("Preliminary inventory, microfilmed")
_("Preservation Film")
_("Preservation film, FHL-GSU")
_("Print Publications")
_("Print editions")
_("Printed Government Documents")
_("Private Holdings")
_("Professional Reports")
_("Publications Style citation")
_("Publications: Books, CDs, Maps, Leaflets & Videos")
_("Publications: Legal Works & Government Documents")
_("Publications: Periodicals, Broadcasts & Web Miscellanea")
_("Radio & television clips")
_("Railroad Retirement Board")
_("Record Books")
_("Record Books, archived off-site")
_("Registers")
_("Research Report")
_("School Records")
_("Series named for editor")
_("Series, emphasis on")
_("Slip laws:")
_("Social Security Administration")
_("Soundex & Miracode, microfilm")
_("Standardized series")
_("State database")
_("State level")
_("State-level")
_("State-level Records")
_("State-level copies")
_("State-sponsored censuses")
_("Statistical database")
_("Statutes:")
_("Student transcript")
_("Tract book")
_("Tradition, recorded")
_("Traditional academic style")
_("U.K. Wales")
_("U.S. Code")
_("UNC microfilm publication")
_("Unpublished narrative")
_("Vertical file")
_("Video")
_("Vital records, amended")
_("Vital records, delayed")
_("Vital-records certificate")
_("Vital-records register")
_("Website as book")
_("archived off-site")
_("basic format")
_("card file")
_("chapter")
_("edited")
_("federal")
_("federal census")
_("held by church")
_("multivolume set")
_("online")
_("personally used")
_("reprint")
_("revised edition")
_("rural")
_("state")
_("supplied by staff")
_("urban")
_("vertical file")