def marc_languages(spec = "008[35-37]:041a:041d")
      translation_map = Traject::TranslationMap.new("marc_languages")

      extractor = MarcExtractor.new(spec, :separator => nil)

      lambda do |record, accumulator|
        codes = extractor.collect_matching_lines(record) do |field, spec, extractor|
          if extractor.control_field?(field)
            (spec.bytes ? field.value.byteslice(spec.bytes) : field.value)
          else
            extractor.collect_subfields(field, spec).collect do |value|
              # sometimes multiple language codes are jammed together in one subfield, and
              # we need to separate ourselves. sigh.
              unless value.length == 3
                # split into an array of 3-length substrs; JRuby has problems with regexes
                # across threads, which is why we don't use String#scan here.
                value = value.chars.each_slice(3).map(&:join)
              end
              value
            end.flatten
          end
        end
        codes = codes.uniq

        translation_map.translate_array!(codes)

        accumulator.concat codes
      end
    end
def marc_languages(spec = "008[35-37]:041a:041d")
      translation_map = Traject::TranslationMap.new("marc_languages")

      extractor = MarcExtractor.new(spec, :separator => nil)

      lambda do |record, accumulator|
        codes = extractor.collect_matching_lines(record) do |field, spec, extractor|
          if extractor.control_field?(field)
            (spec.bytes ? field.value.byteslice(spec.bytes) : field.value)
          else
            extractor.collect_subfields(field, spec).collect do |value|
              # sometimes multiple language codes are jammed together in one subfield, and
              # we need to separate ourselves. sigh.
              unless value.length == 3
                # split into an array of 3-length substrs; JRuby has problems with regexes
                # across threads, which is why we don't use String#scan here.
                value = value.chars.each_slice(3).map(&:join)
              end
              value
            end.flatten
          end
        end
        codes = codes.uniq

        translation_map.translate_array!(codes)

        accumulator.concat codes
      end
    end
maps languages, by default out of 008[35-37] and 041a and 041d

 Can specify other spec if you want, say, 041b (lang of abstract)
 or 041e (lang of librettos), or 041h (lang of original) instead or in addition.

 de-dups values so you don't get the same one twice.

 Exact spec of #marc_languages may change with new user data on what
 works best.